I am trying to work out why the following C++ code works fine with libstdc++, but with libc++ the c_str() results become garbage.
The code simply builds a vector of strings using savedstrings.push_back("blah"), and right after each string is added to the vector, savedstrings.back().c_str() is added to a separate vector of const char*.
So each const char* should point to the corresponding string in the savedstrings vector. This works fine with libstdc++, but with libc++ the const char* at the start of the cstrs vector start to become garbage as the later ones are added.
I'm not sure I understand what is going on here. Is the savedstrings vector moving the earlier strings as new ones are added, thus invalidating the c_str() result? How can I stop this from happening?
vector<string> savedstrings;
vector<const char*> cstrs;
for (int i = 0; i < 10; i++) {
savedstrings.push_back("blah");
cstrs.push_back(savedstrings.back().c_str());
}
vector<string>::iterator si;
for(si=savedstrings.begin();si!=savedstrings.end();++si)
cout << *si << endl;
vector<const char*>::iterator ci;
for(ci=cstrs.begin();ci!=cstrs.end();++ci)
cout << *ci << endl;
If you have any re-allocations in savedstrings, the pointers to the underlying string data may become invalid. De-referencing such pointers would yield undefined behaviour.
You can avoid re-allocations by reserving the right amount of capacity:
vector<string> savedstrings;
savedstrings.reserve(10);
Here's an example showing how a vector's capacity grows as you push elements into is (g++ 4.7.3 on some ubuntu x86_64):
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v;
for (int i = 0; i < 10; ++i){
v.push_back(0);
std::cout << v.capacity() << std::endl;
}
}
Output:
1
2 # re-allocation
4 # re-allocation
4
8 # re-allocation
8
8
8
16 # re-allocation
16
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With