c_str() results from vector<string> become garbage with libc++
c++, garbage-collection, string, vector
Solution
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
Problem
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; ```