【发布时间】:2021-10-02 22:11:36
【问题描述】:
我有一个文本文件,其中包含与姓名、位置和高度相关的数据列表。我的程序将这些数据解析为矢量图,然后使用这些数据使用boost::property_tree 构造一个xml 文件。文本文件大约有 3500 行,程序在第 1773 行始终崩溃:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
起初我以为可能达到了大小限制,但阅读std::string 表明目标计算机应该能够分配所需的大小。无论如何,我决定用std::string::size、std::string::length、std::string::capacity、std::string::max_size 进行测试,分别显示:
...
...
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 增加了一次 std::string::length == std::string::capacity。
gdb bt 编译后调试:
(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
正在读取的文本文件中的示例行:
713.258 235.418 ABCD1234567 2898
代码:
int main(int argc, char **argv)
{
CreateWorld *newWorld = new CreateWorld();
lastModelsParser *lastModels = new lastModelsParser();
/*
Code here reads creates ifs for xml data,
then reads xml successfully into a ptree
*/
vector<lastModelsParser::lastModel> _lastModels;
_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;
}
编辑。 Valgrind 输出
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)
【问题讨论】:
-
std::bad_alloc显示内存快用完了,字符串太大了,输入文件大小是多少? -
如果
bad_alloc由于 RAM 耗尽而没有被抛出,那么很可能是因为您的堆已损坏,导致未来分配失败。我建议在 valgrind(或类似的)下运行你的程序,看看它是否指出了任何非法的内存写入。 -
@prehistoricpenguin 输入文件的大小(以字节为单位)为 436192,包含 3382 行。
std::string::sizestd::string::max_size 时内存如何耗尽? -
std::string::max_size是一个完美的世界价值。如果某处出现问题并耗尽或分散您的存储空间,它可能会超过您可用的存储空间。 -
@JeremyFriesner 谢谢,我已经使用 valgrind 及其工具地块运行。输出太长,无法粘贴到这里,所以我编辑了 OP。