删除[]失败,如何找出原因?

时间:2013-01-16 08:29:30

标签: c++

我有大量的代码一整天都在运行。 每周一次,它在尝试释放一些指针时崩溃:

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

我想找出导致删除失败的原因:重复删除或其他内容。 我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

首先,请注意,回溯包含一个调用malloc_printerr。该函数会将原因写入标准错误,所以请记住将其捕获!

现在,无论是新的/删除类型,双删除还是无效的指针都不匹配,实际的错误发生在实际检测到它的删除之前很久。所以gdb不会有多大用处。你必须记录相关指针发生的任何事情,并在出错时进行挖掘。

  • 如果它是完全无效的指针,它将是未初始化的内存或缓冲区溢出覆盖它。检查所有对象是否具有正确的构造函数,以将任何可能涉及的指针清零。使用valgrind也可以捕获任何问题,使用DUMA librarymudflap(随gcc一起提供),也可以用较少的开销(但精度较低)捕获缓冲区溢出。
  • 如果它是双重删除,请检查在删除任何涉及的指针之后将其清零,除非在析构函数中(如果要在析构函数中删除它,请确保在构造函数中初始化它)。为涉及的指针上的所有操作添加日志消息,当它崩溃时,在指针看起来已经复活的日志中追溯。您也可以尝试为无效指针执行此操作。
  • 如果它不匹配[],请确保在分配[]时始终使用[]删除,否则请确保始终删除完整类型(C ++)接受删除不完整的类型及其未定义的行为。)
  • 上述任何一项也可能是未正确调用任何持有所涉及指针的对象的析构函数的次要影响。无法调用析构函数可能是删除指针类型不正确,删除指向不完整类型或不匹配[] on new和delete的原因。除了审核之外,还要将日志添加到可能相关的任何构造函数和析构函数中,并在日志中检查它们是否正确匹配。

不要忘记始终记录指针值,以便您可以实际匹配条目。您还可能需要编写一些用于分析日志的脚本(找到不匹配的条目)。并有足够的空间;以这种方式生成许多 giga 字节的日志相当容易。

一旦缩小了一些可疑的操作,您可能需要在日志中写回溯。查看backtrace(3)库函数或libunwind

答案 1 :(得分:1)

编写好的单元测试,使用valgrind执行它们,并希望你能抓住这些bug。

除此之外,您可以查看代码并搜索错误(例如,"Good Clues, Easy Bugs" article解释调试技术)。