Reputation: 49
In step 2 I change only the value of name_C
. Why does name_B
also change?
Here is the code:
#include <cstdlib>
#include <dirent.h>
#include <iostream>
#include <fstream>
#include <direct.h>
using namespace std;
int main(int argc, char *argv[])
{
// step 1
char *name_A;
char *name_B;
char *name_C;
string str_L = "hello";
string str_M = "stringVar_A"; ;
name_A = (char *) str_M.c_str();
name_B = (char *) (str_L + "-car-" + str_M).c_str();
name_C = (char *) str_L.c_str();
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl;
cout << " name_C= " << name_C << endl << endl << endl;
// step 2
string str_N = "myStringMyString"; // (in my real code, i can't put this line in step 1)
string str_R = "ABCDEFGHI" + str_N; // (in my real code, i can't put this line in step 1)
name_C = (char *)str_R.c_str(); // change only name_C
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl; // changed, why?
cout << " name_C= " << name_C << endl; // changed, ok.
system("PAUSE");
return EXIT_SUCCESS;
};
Here the output:
(step 1:)
name_A= stringVar_A
name_B= hello-car-stringVar_A
name_C= hello
(step 2:)
name_A= stringVar_A
name_B= ABCDEFGHImyStringMyString
name_C= ABCDEFGHImyStringMyString
With:
string str_N = "myString"; // in step 2...
name_B
does not change.
Why does name_B
change if str_N
is longer than 10 letters?
Can someone help me understand this behavior?
Upvotes: 1
Views: 84
Reputation: 26476
You are causing undefined behaviour.
name_B = (char *) (str_L + "-car-" + str_M).c_str();
you create a temoprary string from the result of std::string::operator + , extract the C-character array out of it, but then no-one really cathes the temporary string.
when a temporary is not caught by const reference - it is destroyed right away. the string destructor de-allocates the inner character array and invalidates name_B.
so, this is undefined behaviour since you try to work with memory address that is no longer valid.
Upvotes: 3
Reputation: 40070
std::string::c_str()
returns a pointer to an internal buffer of a std::string
with the guarantee that:
c_str()
; c_str() + size()
] is valid.In your case, name_B
points to an internal buffer of a temporary object name_B = (str_L + "-car-" + str_M).c_str();
which will lead to an Undefined Behaviour when you'll try to use it.
When you make some modifications on your stack (you define two new std::string
s), you probably alter the stack place where your name_B
points to (since the memory reserved by your temporary has been freed).
If you really have to get old style C-strings from your std::string
s, make sure:
std::string::c_str()
is no longer used when the std::string
is modified or destroyed,std::string::c_str()
from a temporary.Upvotes: 2
Reputation: 234665
The pointer returned by a call to c_str
is only valid for as long as the corresponding std::string
stays in scope and is unmodified.
The behaviour in accessing it beyond that is undefined.
For example, (str_L + "-car-" + str_M).c_str();
is returning you the c_str
of an anonymous temporary. It will be immediately invalid after the assignment. In your case, name_B
is invalidated.
Also, don't cast away the const char*
return of c_str()
. It's const
for a very good reason: you should not attempt to modify the string contents through that pointer.
Upvotes: 4