Stringstream to Vector throws std::bad_alloc

2019-09-03 10:59发布

问题:

I was tinkering with Boost Property Tree a bit, and I came across this example. I needed to convert the final result to vector, so I just added one more line after

write_json(ss, root);

like this:

std::vector<char> testVec(std::begin(ss.str()), std::end(ss.str()));

I have also tried this instead:

std::string someString = ss.str()
char* someArray = (char*)someString.c_str();
std::vector<char> someVec(someArray, someArray+sizeof(someArray));

In both the cases, I am getting this error:

terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc

Any hints what I am doing wrong? It is not a problem of property tree, I gather. It is a problem of string to vector conversion. I guess this makes sense, because vectors are only supposed to be one dimensional, but I have no clue how to convert that string to vector and get it back again.

回答1:

This fails:

std::vector<char> testVec(std::begin(ss.str()), std::end(ss.str())); 

because the std::begin() and std::end() are not associated with same std::string instance. The ss.str() returns a new std::string instance each time, it does not return a std::string& to some internal member.

This is incorrect:

std::vector<char> someVec(someArray, someArray+sizeof(someArray)); 

because sizeof(someArray) is sizeof(char*). If there is less than sizeof(char*) elements in someArray an attempt will be made to read memory that should not.

A possible solution:

std::string someString = ss.str();
std::vector<char> someVec(someString.begin(), someString.end());


回答2:

sizeof() isn't giving you the length of the array, because c strings don't know their length (null-terminated). It's just providing the size of the memory location for the pointer at the beginning of the array, which is why you can reference past the end of the string using operator[] if you're not careful.

Another solution is to overload sizeof to iterate through the string until it hits the null terminator, but that seems like something you could do with built in things without going through the extra work.