Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string.c_str() deallocation necessary?

My code converts C++ strings to CStrings somewhat often, and I am wondering if the original string is allocated on the stack, will the CString be allocated on the stack as well? For instance:

string s = "Hello world"; char* s2 = s.c_str(); 

Will s2 be allocated on the stack, or in the heap? In other words, will I need to delete s2?

Conversely, if I have this code:

string s = new string("Hello, mr. heap..."); char* s2 = s.c_str(); 

Will s2 now be on the heap, as its origin was on the heap?

To clarify, when I ask if s2 is on the heap, I know that the pointer is on the stack. I'm asking if what it points to will be on the heap or the stack.

like image 440
Georges Oates Larsen Avatar asked Jan 12 '12 22:01

Georges Oates Larsen


People also ask

Do I need to delete c_str?

Will I need to delete s2? No, the character array object returned by c_str is owned by the string object.

What is string c_str ()?

The basic_string::c_str() is a builtin function in C++ which returns a pointer to an array that contains a null-terminated sequence of characters representing the current value of the basic_string object.

Why is c_str used?

c_str() converts a C++ string into a C-style string which is essentially a null terminated array of bytes. You use it when you want to pass a C++ string into a function that expects a C-style string (e.g. a lot of the Win32 API, POSIX style functions, etc).

Is string c_str null terminated?

c_str returns a "C string". And C strings are always terminated by a null character. This is C standard.


2 Answers

string s = "Hello world"; char* s2 = s.c_str(); 

Will s2 be allocated on the stack, or in the heap? In other words... Will I need to delete s2?

No, don't delete s2!

s2 is on the stack if the above code is inside a function; if the code's at global or namespace scope then s2 will be in some statically-allocated dynamically-initialised data segment. Either way, it is a pointer to a character (which in this case happens to be the first 'H' character in the ASCIIZ representation of the text content of s). That text itself is wherever the s object felt like constructing that representation. Implementations are allowed to do that however they like, but the crucial implementation choice for std::string is whether it provides a "short-string optimisation" that allows very short strings to be embedded directly in the s object and whether "Hello world" is short enough to benefit from that optimisation:

  • if so, then s2 would point to memory inside s, which will be stack- or statically-allocated as explained for s2 above
  • otherwise, inside s there would be a pointer to dynamically allocated (free-store / heap) memory wherein the "Hello world\0" content whose address is returned by .c_str() would appear, and s2 would be a copy of that pointer value.

Note that c_str() is const, so for your code to compile you need to change to const char* s2 = ....

You must notdelete s2. The data to which s2 points is still owned and managed by the s object, will be invalidated by any call to non-const methods of s or by s going out of scope.

string s = new string("Hello, mr. heap..."); char* s2 = s.c_str(); 

Will s2 now be on the heap, as its origin was on the heap?

This code doesn't compile, as s is not a pointer and a string doesn't have a constructor like string(std::string*). You could change it to either:

string* s = new string("Hello, mr. heap..."); 

...or...

string s = *new string("Hello, mr. heap..."); 

The latter creates a memory leak and serves no useful purpose, so let's assume the former. Then:

char* s2 = s.c_str(); 

...needs to become...

char* s2 = s->c_str(); 

Will s2 now be on the heap, as its origin was on the heap?

Yes. In all the scenarios, specifically if s itself is on the heap, then:

  • even if there's a short string optimisation buffer inside s to which c_str() yields a pointer, it must be on the heap, otherwise
  • if s uses a pointer to further memory to store the text, that memory will also be allocated from the heap.

But again, even knowing for sure that s2 points to heap-allocated memory, your code does not need to deallocate that memory - it will be done automatically when s is deleted:

string* s = new string("Hello, mr. heap..."); const char* s2 = s->c_str(); ...use s2 for something... delete s;   // "destruct" s and deallocate the heap used for it... 

Of course, it's usually better just to use string s("xyz"); unless you need a lifetime beyond the local scope, and a std::unique_ptr<std::string> or std::shared_ptr<std::string> otherwise.

like image 51
Tony Delroy Avatar answered Oct 23 '22 01:10

Tony Delroy


c_str() returns a pointer to an internal buffer in the string object - you don't ever free()/delete it.

It is only valid as long as the string it points into is in scope. In addition if you call a non-const method of the string object it is no longer guaranteed to be valid.

http://www.cplusplus.com/reference/string/string/c_str/

(Edited for clarity based on comments below)

like image 23
Brian Roach Avatar answered Oct 23 '22 01:10

Brian Roach