string

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • eastern_strider

    #1

    string

    Hi,

    Is it safe to have a pointer to a string.c_str() created locally inside
    a function? For example, would the following code give me headace if a
    try to use "c" after calling foo() ?

    const char *c;

    void foo ()
    {
    string str = "Hello";
    c = str.c_str();
    }

    Thanks,
    Oguz

  • Bart

    #2
    Re: string

    eastern_strider wrote:
    Hi,
    >
    Is it safe to have a pointer to a string.c_str() created locally inside
    a function?
    No.
    For example, would the following code give me headace if a
    try to use "c" after calling foo() ?
    >
    const char *c;
    >
    void foo ()
    {
    string str = "Hello";
    c = str.c_str();
    }
    You shouldn't do this. You can normally call functions that take a
    C-style string without any problems (as long as they don't modify the
    string) as these normally just copy the string into their own internal
    buffer. However, having pointers to char in your own code is just a bad
    idea. Why not just have a string object that holds the string?

    Regards,
    Bart.

    Comment

    • Default User

      #3
      Re: string

      eastern_strider wrote:
      Hi,
      >
      Is it safe to have a pointer to a string.c_str() created locally
      inside a function? For example, would the following code give me
      headace if a try to use "c" after calling foo() ?
      >
      const char *c;
      >
      void foo ()
      {
      string str = "Hello";
      c = str.c_str();
      }
      Yes, it would. str ceases to exist at the end of that scope, and any
      memory it allocated is almost suredly deallocated. Otherwise every use
      of a string would be memory leak.




      Brian




      Comment

      • tugboat90

        #4
        Re: string

        I'm not quite sure about the memory being deallocated at the end of the
        function. I've run into several instances where I've had memory leaks
        from CStrings that haven't been deallocated.

        If I remember correctly there are functions inside CString to help
        clean up. I don't remember the exact function calls, but they were
        something to the extent of "EmptyStringCon tents" and then
        "FreeUnusedMemo ry".

        On Oct 12, 4:44 pm, "Default User" <defaultuse...@ yahoo.comwrote:
        eastern_strider wrote:
        Hi,
        >
        Is it safe to have a pointer to a string.c_str() created locally
        inside a function? For example, would the following code give me
        headace if a try to use "c" after calling foo() ?
        >
        const char *c;
        >
        void foo ()
        {
        string str = "Hello";
        c = str.c_str();
        }Yes, it would. str ceases to exist at the end of that scope, and any
        memory it allocated is almost suredly deallocated. Otherwise every use
        of a string would be memory leak.
        >
        Brian

        Comment

        • Larry Smith

          #5
          Re: string

          On Oct 12, 4:44 pm, "Default User" <defaultuse...@ yahoo.comwrote:
          >eastern_stride r wrote:
          >>Hi,
          >>Is it safe to have a pointer to a string.c_str() created locally
          >>inside a function? For example, would the following code give me
          >>headace if a try to use "c" after calling foo() ?
          >>const char *c;
          >>void foo ()
          >>{
          >> string str = "Hello";
          >> c = str.c_str();
          >>}Yes, it would. str ceases to exist at the end of that scope, and any
          >memory it allocated is almost suredly deallocated. Otherwise every use
          >of a string would be memory leak.
          >>
          >Brian
          >
          tugboat90 wrote:
          I'm not quite sure about the memory being deallocated at the end of the
          function. I've run into several instances where I've had memory leaks
          from CStrings that haven't been deallocated.
          >
          If I remember correctly there are functions inside CString to help
          clean up. I don't remember the exact function calls, but they were
          something to the extent of "EmptyStringCon tents" and then
          "FreeUnusedMemo ry".
          >
          Please don't top-post...

          A C++ std::string is NOT a CString.

          CString is Microsoft specific.

          std::string does not have cleanup issues.


          Comment

          • Jim Langston

            #6
            Re: string

            "eastern_stride r" <oguzakyuz@gmai l.comwrote in message
            news:1160688787 .608579.52880@m 7g2000cwm.googl egroups.com...
            Hi,
            >
            Is it safe to have a pointer to a string.c_str() created locally inside
            a function? For example, would the following code give me headace if a
            try to use "c" after calling foo() ?
            >
            const char *c;
            >
            void foo ()
            {
            string str = "Hello";
            c = str.c_str();
            }
            Yes and No. It depends on what you plan on doing with the string pointer
            after you assign it. The pointer returned to by .c_str() will remain valid
            until the std::string is changed somehow (characters added, erased, etc..)
            or the std::string goes out of scope. With such limitations it's easy to
            get bitten by the data becoming invalid. If you have an extremely good
            reason for doing this (and I actually can't think of one), and document it
            in code, and know what you're doing, it should be okay, but with all tose
            this and that and that, it is safer, IMO, just not to do that.

            So the question becomes, *why* would you want to assign the pointer returned
            via .c_str() to a variable? For what purpose? It is a constant c-string
            and so you can't change the data. So why do you need to keep the pointer
            around?


            Comment

            • Greg

              #7
              Re: string


              eastern_strider wrote:
              Hi,
              >
              Is it safe to have a pointer to a string.c_str() created locally inside
              a function? For example, would the following code give me headace if a
              try to use "c" after calling foo() ?
              >
              const char *c;
              >
              void foo ()
              {
              string str = "Hello";
              c = str.c_str();
              }
              No, as others have pointed out c becomes a stale pointer as soon as
              foo() returns to its caller.

              As a rule of thumb, call std::string::c_ str() only when passing the
              contents of a std::string object to a function that expects a const
              char * parameter (such as many POSIX routines). Limiting
              std::string-to-C-string-pointer conversions to this one case ensures
              that the converted const char * pointer never becomes stale. Otherwise,
              just use std::string's consistently throughout the rest of your code.

              Greg

              Comment

              • Greg

                #8
                Re: string

                eastern_strider wrote:
                Hi,
                >
                Is it safe to have a pointer to a string.c_str() created locally inside
                a function? For example, would the following code give me headace if a
                try to use "c" after calling foo() ?
                >
                const char *c;
                >
                void foo ()
                {
                string str = "Hello";
                c = str.c_str();
                }
                Yes, this program will have a serious problem: as others have pointed
                out c becomes a stale pointer as soon as foo() returns to its caller.

                As a rule of thumb, call std::string::c_ str() only when passing the
                contents of a std::string object to a function that expects a const
                char * parameter (such as many POSIX routines). Limiting
                std::string-to-C-string-pointer conversions to this one case ensures
                that the converted const char * pointer never becomes stale. Otherwise,
                just use std::string's consistently throughout the rest of your code.

                Greg

                Comment

                • eastern_strider

                  #9
                  Re: string

                  Hi,

                  Thanks for all replies. I've just given the sample code for
                  illustration and what I'm exactly doing is very similar to Greg's
                  example.

                  I'm using an external library function which accepts c-style strings as
                  argument. However, it just keeps a pointer to this argument. That is,
                  it DOES NOT actually copy it to an internal buffer. So my real use of
                  c_str() is just like:

                  MyClass::MyClas s()
                  {
                  string str = "Hello";
                  BaseClass::add (str.c_str());
                  }

                  Now what "add" does is:

                  void BaseClass::add (const char *item)
                  {
                  item_ptr = item; // item_ptr is a const char* member of BaseClass
                  }

                  So this is the whole story. The question is, throughout the rest of the
                  program, does item_ptr continue to point to a valid location? I
                  believe I can ensure that explicitly by definining:

                  string* str = new string ("Hello");

                  inside my constructor. However, I've been wondering whether such an
                  explicit allocation is actually necessary in this case.

                  All answers are very much appreciated.
                  Oguz

                  Greg wrote:
                  eastern_strider wrote:
                  Hi,

                  Is it safe to have a pointer to a string.c_str() created locally inside
                  a function? For example, would the following code give me headace if a
                  try to use "c" after calling foo() ?

                  const char *c;

                  void foo ()
                  {
                  string str = "Hello";
                  c = str.c_str();
                  }
                  >
                  Yes, this program will have a serious problem: as others have pointed
                  out c becomes a stale pointer as soon as foo() returns to its caller.
                  >
                  As a rule of thumb, call std::string::c_ str() only when passing the
                  contents of a std::string object to a function that expects a const
                  char * parameter (such as many POSIX routines). Limiting
                  std::string-to-C-string-pointer conversions to this one case ensures
                  that the converted const char * pointer never becomes stale. Otherwise,
                  just use std::string's consistently throughout the rest of your code.
                  >
                  Greg

                  Comment

                  • Florian Stinglmayr

                    #10
                    Re: string

                    eastern_strider wrote:
                    >
                    I'm using an external library function which accepts c-style strings as
                    argument. However, it just keeps a pointer to this argument. That is,
                    it DOES NOT actually copy it to an internal buffer. So my real use of
                    c_str() is just like:
                    >
                    MyClass::MyClas s()
                    {
                    string str = "Hello";
                    BaseClass::add (str.c_str());
                    }
                    >
                    Now what "add" does is:
                    >
                    void BaseClass::add (const char *item)
                    {
                    item_ptr = item; // item_ptr is a const char* member of BaseClass
                    }
                    >
                    Why not:

                    void BaseClass::add (const std::string& item )
                    {
                    _sitem = item;
                    my_ext_library_ which_accepts_c strings(_sitem. c_str());
                    }
                    So this is the whole story. The question is, throughout the rest of the
                    program, does item_ptr continue to point to a valid location?
                    No, since the std::string "str" gets out of scope and the memory it
                    contained is deleted. As pointed out earlier.
                    I believe I can ensure that explicitly by definining:
                    >
                    string* str = new string ("Hello");
                    >
                    You don't have to use pointers. If you pass a C style string to the
                    constructor of an std::string it automatically creates a copy of the
                    string.

                    I urge you to get a C++ book.

                    Comment

                    • Salt_Peter

                      #11
                      Re: string


                      eastern_strider wrote:
                      Hi,
                      >
                      Thanks for all replies. I've just given the sample code for
                      illustration and what I'm exactly doing is very similar to Greg's
                      example.
                      >
                      I'm using an external library function which accepts c-style strings as
                      argument. However, it just keeps a pointer to this argument. That is,
                      it DOES NOT actually copy it to an internal buffer. So my real use of
                      c_str() is just like:
                      >
                      MyClass::MyClas s()
                      {
                      string str = "Hello";
                      BaseClass::add (str.c_str());
                      }
                      >
                      Now what "add" does is:
                      >
                      void BaseClass::add (const char *item)
                      {
                      item_ptr = item; // item_ptr is a const char* member of BaseClass
                      }
                      >
                      So this is the whole story. The question is, throughout the rest of the
                      program, does item_ptr continue to point to a valid location? I
                      believe I can ensure that explicitly by definining:
                      >
                      string* str = new string ("Hello");
                      >
                      inside my constructor. However, I've been wondering whether such an
                      explicit allocation is actually necessary in this case.
                      >
                      item_ptr is not valid. You'll need to manage the allocation of a
                      std::string. That does not mean you need a heap allocation. You can
                      keep a const std::string member in MyClass. You'll need to observe
                      what, if any, ctor is available for that BaseClass.

                      Now there are 2 issues you need to be aware of: copy ctors and
                      inheritence.
                      What follows is not neccessarily correct for you. You may prefer
                      overiding add(...).

                      #include <string>

                      class MyClass : public BaseClass
                      {
                      const std::string s_;
                      public:
                      MyClass(std::st ring s) : BaseClass() : s_(s)
                      {
                      add(s_.c_str()) ;
                      }
                      MyClass(const MyClass& r_copy) : BaseClass(), s_(r_copy.s_) // const
                      {
                      add(s_.c_str()) ; // reseated pointer
                      }
                      };

                      If you need to copy an instance of MyClass, you certainly don't want
                      the BaseClass pointer (const char* item) to point to the original
                      instance. If you don't plan to copy at all, disable copy construction.
                      Better an error than a bug you'll regret.

                      class MyClass : public BaseClass
                      {
                      const std::string s_;
                      public:
                      MyClass(std::st ring s) : BaseClass() : s_(s)
                      {
                      add(s_.c_str()) ;
                      }
                      MyClass(const MyClass& r_copy); // disabled
                      };

                      Lastly: inheritence.
                      Don't use pointers to BaseClass objects to store MyClass instances if
                      BaseClass does not have a virtual d~tor. I'm willing to bet that the
                      BaseClass is using a non-virtual compiler-generated ctor.

                      Finally, don't use pointers unless you absolutely have to. Always
                      prefer references.

                      Comment

                      • eastern_strider

                        #12
                        Re: string

                        Thanks for your kind! reply, but it seems misleading to me.

                        Please correct me if I'm wrong but you suggest that:

                        const char* foo ()
                        {
                        std::string str ("Hello");
                        return str.c_str();
                        }

                        int main()
                        {
                        const char *c = foo();
                        // c can be used safely in the rest of the program.
                        }

                        I'm not sure that this is as safe as:

                        const char* foo ()
                        {
                        std::string* str = new string ("Hello");
                        return str->c_str();
                        }

                        because in the latter we guarantee that the memory associated with str
                        will continue to exist even after foo returns. However, in the former
                        version that memory might be freed once foo returns since str is a
                        local variable.

                        Cheers,
                        Oguz








                        Florian Stinglmayr wrote:
                        eastern_strider wrote:

                        I'm using an external library function which accepts c-style strings as
                        argument. However, it just keeps a pointer to this argument. That is,
                        it DOES NOT actually copy it to an internal buffer. So my real use of
                        c_str() is just like:

                        MyClass::MyClas s()
                        {
                        string str = "Hello";
                        BaseClass::add (str.c_str());
                        }

                        Now what "add" does is:

                        void BaseClass::add (const char *item)
                        {
                        item_ptr = item; // item_ptr is a const char* member of BaseClass
                        }
                        >
                        Why not:
                        >
                        void BaseClass::add (const std::string& item )
                        {
                        _sitem = item;
                        my_ext_library_ which_accepts_c strings(_sitem. c_str());
                        }
                        >
                        So this is the whole story. The question is, throughout the rest of the
                        program, does item_ptr continue to point to a valid location?
                        >
                        No, since the std::string "str" gets out of scope and the memory it
                        contained is deleted. As pointed out earlier.
                        >
                        I believe I can ensure that explicitly by definining:

                        string* str = new string ("Hello");
                        >
                        You don't have to use pointers. If you pass a C style string to the
                        constructor of an std::string it automatically creates a copy of the
                        string.
                        >
                        I urge you to get a C++ book.

                        Comment

                        • tragomaskhalos

                          #13
                          Re: string


                          On Oct 13, 9:26 am, "eastern_stride r" <oguzak...@gmai l.comwrote:
                          Thanks for your kind! reply, but it seems misleading to me.
                          >
                          Please correct me if I'm wrong but you suggest that:
                          >
                          const char* foo ()
                          {
                          std::string str ("Hello");
                          return str.c_str();
                          >
                          }int main()
                          {
                          const char *c = foo();
                          // c can be used safely in the rest of the program.
                          NOOO ! Noone is suggesting this - it doesn't work. str goes out of
                          scope when you exit foo and the buffer returned is therefore invalid.
                          >
                          const char* foo ()
                          {
                          std::string* str = new string ("Hello");
                          return str->c_str();
                          >
                          }
                          This is also wrong but for a different reason - the memory will not be
                          freed (there is no "might" about it) so although you can use the
                          returned const char* safely, you now have a memory leak because you
                          have no way of destroying the newed string.

                          You have to get what's happening with local and heap-based objects
                          clear in your head to be able to use C++ properly.

                          Comment

                          Working...