Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there issue will stringstream.str().c_str()? [duplicate]

For Code:

stringstream ss("012345678901234567890123456789012345678901234567890123456789");  

some articles said it is wrong for followed usage due to ss.str return temp object and will destructered before call .c_str();

 const char* cstr2 = ss.str().c_str();  

but I run the example, there is no problem? how to understand?

like image 741
jiafu Avatar asked Jan 10 '14 01:01

jiafu


2 Answers

But I run the example, there is no problem?

In fact, there's nothing wrong in the expression:

const char* cstr2 = ss.str().c_str();

The temporary (copy) object returned by ss.str() will live long enough to let you get the underlying c-string with c_str().

Of course by the end of the expression you'll have a const char pointer to an object that is probably deallocated (this depends heavily on the std::basic_string implementation).

Therefore this is likely not a good idea. What you should do instead is:

auto x = ss.str();
const char* cstr2 = x.c_str(); 

The above code won't get you any trouble, since the returned value of str() is now being copied/is not a temporary anymore, and the access to x.c_str() will give you a valid pointer.

like image 124
Shoe Avatar answered Sep 22 '22 15:09

Shoe


Yet another wonderful C++ landmine.

Basically, your pointer references a block of memory (C string) that is referencing a temporary copy (string) of whatever was in the stream at the time you did the double affectation.

str() returns a temporary object.

Life expectancy of temporary objects is rather short. Either someone takes a reference to them immediately (e.g. string& s = ss.str()) or they die at the end of the statement they were born in.

However, the compiler allows to get a reference to the same block of memory through c_str(), but indirectly, so it flies under the compiler's radar. What a pity.

So your pointer will indeed be valid at the time c_str gets it, but just for about as long as if you did something like this in plain old C:

const char * cstr2;
{
    char ss_str[100];            // str() return value is dynamically created
    char * c_str = &ss_str_[10]; // c_str() takes a reference to some part of it
    cstr2 = c_str;               // cstr2 takes an indirect reference to str() ret. val.
}                                // compiler pulls the plug on str() ret. val.

So, right after the end of this very statement, c_str is already referencing the cadaver of whatever string str() returned.

Now since temporary objects are allocated on the stack, you may well never notice the problem. Object deallocation in itself will likely not modify the defunct string value, but as soon as the compiler will reuse this bit of stack, the proverbial guru will have something to meditate over.

like image 34
kuroi neko Avatar answered Sep 22 '22 15:09

kuroi neko