I have a text file which contains a list of data relating to name, position, and height. My program parses this data into a vector map, then uses this data to construct an xml file using boost::property_tree
. The text file is about 3500 lines, and the program consistently crashes at line 1773 with:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
At first I thought maybe the size limit was being reached, but reading up on std::string
shows that the target computer should be able to allocate the size required. Regardless, I decided to test with std::string::size
, std::string::length
, std::string::capacity
, std::string::max_size
which showed (respectively):
...
...
6572094845 6572094845 6626476032 9223372036854775807
6579537815 6579537815 6626476032 9223372036854775807
6586984998 6586984998 6626476032 9223372036854775807
6594436394 6594436394 6626476032 9223372036854775807
6601892003 6601892003 6626476032 9223372036854775807
6609351825 6609351825 6626476032 9223372036854775807
6616815856 6616815856 6626476032 9223372036854775807
6624284100 6624284100 6626476032 9223372036854775807
std::string::capacity
was seen to increase once std::string::length == std::string::capacity
.
gdb bt after compiling for debug:
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007fd67037e921 in __GI_abort () at abort.c:79
#2 0x00007fd6709d3957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007fd6709d9ae6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007fd6709d9b21 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007fd6709d9d54 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007fd6709da2dc in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007fd670a6bb8b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007fd670a6d133 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x000056104c176f3a in main (argc=1, argv=0x7ffc0af8b9a8) at /home/code/hello_world/createWorld.cpp:224
Example line in text file being read:
713.258 235.418 ABCD1234567 2898
Code:
int main(int argc, char **argv)
{
CreateWorld *newWorld = new CreateWorld();
lastModelsParser *lastModels = new lastModelsParser();
const string filenameModel = "model.sdf";
const string fileNameWorld = "TEMPLATE_default_world.xml";
string lastModels = "lastmodels.txt";
ptree ptWorld, ptModel, ptNewWorld, ptNewModel;
std::ifstream ifsModel(filenameModel,std::ifstream::binary);
std::ifstream ifsWorld(fileNameWorld,std::ifstream::binary);
std::ofstream newWorldFile("NEW_WORLD.xml");
std::ostringstream worldOSS, modelOSS, newWorldOSS;
read_xml(ifsWorld, ptWorld, boost::property_tree::xml_parser::trim_whitespace); // read xml data into ptree
read_xml(ifsModel, ptModel, boost::property_tree::xml_parser::trim_whitespace); // read xml data into ptree
vector<lastModelsParser::lastModel> _lastModels;
lastModels->ParseToXML(lastModelsFile);
_lastModels = lastModels->getlastModels();
uint16_t lastModelsEntry = 0;
std::string newModelString;
for(auto i:_lastModels){
ptNewModel = newWorld->modelModifier(ptModel,
_lastModels.at(lastModelsEntry).pX,
_lastModels.at(lastModelsEntry).pY,
_lastModels.at(lastModelsEntry).name,
_lastModels.at(lastModelsEntry).height);
boost::property_tree::xml_parser::write_xml_element(modelOSS, ptNewModel.front().first, ptNewModel.back().second, 1, xml_settings);
newModelString.append(modelOSS.str()); // CRASHES HERE
lastModelsEntry++;
}
// append to world.xml
boost::property_tree::write_xml(worldOSS, ptWorld, xml_settings); // write xml data into OSStreams
boost::property_tree::write_xml(modelOSS, ptModel, xml_settings); // write xml data into OSStreams
size_t worldPos = worldOSS.str().find("</world>");
std::string newWorldString = worldOSS.str().insert(worldPos,newModelString+"\n\t");
newWorldFile << newWorldString ;
delete(lastModels);
delete(newWorld);
return EXIT_SUCCESS;
}
Edit. Valgrind output
valgrind --tool=massif --massif-out-file=memleak.txt ./createNewWorld
heap_tree=detailed
n2: 6636657886 (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
n2: 6626476282 0x5160B89: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
n2: 6626476282 0x5162131: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
n0: 6626476033 0x149F38: main (in /home/code/hello_world/createNewWorld)
n0: 249 in 2 places, all below massif's threshold (1.00%)
n0: 0 in 2 places, all below massif's threshold (1.00%)
n0: 10181604 in 18 places, all below massif's threshold (1.00%)
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out_1.txt ./createNewWorld
...
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
==4758== Warning: set address range perms: large range [0xee015040, 0x1b37d5041) (undefined)