2013-01-16 82 views
2

我有一大堆整天都在运行的代码。删除[]失败,如何找出原因?

delete [] p 

回溯追踪(用gdb):

0x00007f4f709f2885 in raise() from /lib64/libc.so.6 
0x00007f4f709f4065 in abort() from /lib64/libc.so.6 
0x00007f4f70a2f7a7 in __libc_message() from /lib64/libc.so.6 
0x00007f4f70a350c6 in malloc_printerr() from /lib64/libc.so.6 

我想找出导致删除失败: 每周一次,它试图释放一些指针时崩溃重复的删除或者是其他东西。 我该怎么做?

+3

如果你希望人们能够帮助你,第一步就是实际发布代码。如果一般的“我如何调试这种问题”的建议是你想要的,我会开始记录每次删除被调用,谁叫它何时和为什么。并开始梳理,找到bug的来源。 – Oren

+0

你将需要展示更多的代码。你也可以试试valgrind。 – goji

+0

我建议通过valgrind运行你的程序,希望找到你的bug。 – Grizzly

回答

1

编写好的单元测试,使用valgrind执行它们,并希望您能够捕获错误。除此之外,您可以查看您的代码并搜索错误(例如,"Good Clues, Easy Bugs" article解释调试技术)。

2

首先,请注意,回溯包含呼叫malloc_printerr。该函数会将原因写入标准错误,所以请记住捕获它!现在

无论是不匹配的新的/删除类型,双删除或无效的指针干脆,以前删除,实际上检测到它实际发生的错误长。所以gdb不会有太大用处。你将不得不记录发生在相关指针上的任何事情,并在出错时进行挖掘。

  • 如果它是完全无效的指针,它可能是未初始化的内存或覆盖它的缓冲区溢出。查看所有对象都有正确的构造函数,它们可以将可能涉及的任何指针归零。使用DUMA librarymudflap(附带gcc),也可以用valgrind捕获任一问题,也可以用更少的开销(但精度更低)捕获缓冲区溢出。
  • 如果是双删除,审核,你在析构函数删除它,除非以后零出任何涉及指针(如果你在析构函数中删除,请确保您在构造函数初始化它)。所有操作添加上所涉及的指针日志信息和崩溃时,追溯其中指针似乎已经复活在日志中。您也可以尝试为无效指针做到这一点。
  • 如果它不匹配[],请确保您始终使用[]删除[],否则永远不要确保始终删除完整类型(C++接受删除不完整类型和它的未定义行为)。
  • 任何上述的组合也可以是不能正确调用保持所涉及的指针的任何对象的析构函数继发效应。无法调用析构函数可能是删除具有不正确类型的指针,删除指向不完整类型的指针或不匹配[]上新建和删除。除了审查之外,还可以将日志添加到任何可能相关的构造函数和析构函数中,并在日志中检查它们是否正确匹配。

不要忘记始终记录指针值,以便实际上可以匹配条目。您也可能需要编写一些脚本来分析日志(找到不匹配的条目)。并有足够的空间;这样很容易生成很多这样的日志字节。

一旦你缩小是犯罪嫌疑人一些操作,你可能需要编写回溯到日志。请查看backtrace(3)库函数或libunwind