Valgrind通常非常可靠地发现内存泄漏,所以您确定这是内存泄漏吗?
堆分析器可以帮助您查看正在创建的对象以及它们是否符合您的预期。Massif是一种可能证明有用的工具。
正如其他人所指出的那样,这可能不是一个简单的泄漏。更有可能的是错误的强制转换,使其误解某个对象的类型。或者是缓冲区下溢/上溢,或者是整数翻转(一些32位有符号偏移超过2Gig?),或者是悬空指针....
根据我的经验,在构建具有各种指针的复杂结构时,您需要一个结构的正式规范。特别重要的是一组不变量。有了这些,构建一个测试套件和运行时验证器,可以确保您的数据仍然一致且整洁。
我建议你首先尝试使用gdb解决问题,因为它是发现segfault发生时发生了什么的#1工具。然后运行程序直到它崩溃,并确保系统生成核心文件(使用ulimit -c unlimited
允许创建核心文件,如果它是一个守护进程,请注意必须为实际运行守护进程的用户执行此操作)。此时,您可以使用带有core文件的gdb查找segfault发生的位置(参见backtrack
命令)。
这也可能是堆栈溢出(当然这很奇怪,但它也是符合你所有问题的可能性)。例如,如果一个函数在一段时间后调用自身(隐式或显式),就可能会发生这种情况。我再次强调,这将是一个奇怪而非常罕见的问题,但这是我在阅读所有答案和问题后想到的事情。
Valgrind有一个缺点,就是在多线程应用程序中查找泄漏可能会比较困难。如果您的泄漏是由竞争条件引起的,在调试期间它将消失,因为Valgrind会序列化所有内容。
我调试过的几乎每个“泄漏”,特别是在Java中,都是标准集合中无限增长的结果。例如:从不清理的向量、超出预期的字典等。如果Valgrind没有发现任何问题,那么很有可能这不是真正的泄漏。
你的编译器或链接器有没有出现任何奇怪的警告?与libstdc++有关的吗?我们曾经遇到过一个问题,即同时链接两个不同版本的libstdc++(5和6),这给我们带来了可怕的内存泄漏。
我曾经听说过,有时候如果内存不足,new操作符会返回NULL而不是抛出异常。也许这就导致了段错误?