Reputation: 702
I'm writing a code where I need to write a large string into memory.
I used a stringstream object to do so, but something odd to me happens: even if the size of the underlying string buffer has not exceeded the maximum size of a string object my program crashes with a BAD_ACCESS
error.
I've created a test program like this:
#include <sstream> // std::stringstream
#include <iostream> // std::cout
int main(int argc, const char * argv[]) {
std::stringstream stream;
std::string string;
std::cout << "Max string size: " << string.max_size() << "\n";
for (int i = 0; true; i++) {
if (i >= 644245094) {
stream.seekg(0, std::ios::end);
std::stringstream::pos_type size = stream.tellg();
stream.seekg(0, std::ios::beg);
std::cout << "Size of stringstream: " << size << "\n";
}
stream << "hello";
}
return 0;
}
That if (i >= 644245094)
inside the loop is only used to print the size of the stringstream buffer just before the program crashes. I've used my debugger to see which was the number of the last iteration and used it to print the size of the buffer just before the crash happens.
This is the output I get:
Max string size: 18446744073709551599
Size of stringstream: 3221225470
After this the program crashes.
I thought that the cause might be because the program fills up my computer's RAM but the memory used by this program is ~6.01GB so not enough to fill up my RAM. For the record I have a 16GB RAM Macbook Pro.
What could be the problem? Am I missing something about how <<
operator works?
Thank you in advance!
Upvotes: 1
Views: 779
Reputation: 2857
The behaviour of a std::stringstream when it gets full and fails may not be consistent across all platforms.
I modified your code and rain it on Yocto 3.19.0-32 64-bit, with gcc 5.4.1. I did not get an exception thrown, rather the stream set one of its failure mode bits.
The code I ran was:
#include <sstream> // std::stringstream
#include <iostream> // std::cout
std::stringstream::pos_type get_size(std::stringstream& stream)
{
stream.seekg(0, std::ios::end);
std::stringstream::pos_type size = stream.tellg();
stream.seekg(0, std::ios::beg);
return size;
}
int main(int argc, const char * argv[])
{
std::stringstream stream;
std::string string;
std::cout << "Max string size: " << string.max_size() << std::endl;
std::stringstream::pos_type size;
for (unsigned long i = 0; true; ++i)
{
size = get_size(stream);
stream.write("x", 1);
if (stream.fail())
{
std::cout << "Fail after " << i + 1 << " insertions" << std::endl;
std::cout << "Size of stringstream just before fail: " << size << std::endl;
break;
}
}
size = get_size(stream);
std::cout << "Size of stringstream just after fail: " << size << std::endl;
return 0;
}
And I got the following output, which shows that my stringstream filled and failed 56 bytes short of 8GB:
Max string size: 4611686018427387897
Fail after 8589934536 insertions
Size of stringstream just before fail: 8589934535
Size of stringstream just after fail: -1
Can you not use a different container and pre-allocate the memory, instead of using such a large stringstream?
Upvotes: 1