【问题标题】:How to debug a strange memory leak (C++)如何调试奇怪的内存泄漏(C++)
【发布时间】:2011-01-20 06:20:35
【问题描述】:

我正在编写一个 linux 恶魔,目前它运行良好,但它会泄漏内存(而且很糟糕 - 几个小时后,它在使用 60% 的系统内存后出现段错误)。奇怪的是,我只使用了 new/delete 运算符,并且在 main 函数周围有一个 try/catch 块,所以这不是 new 抛出的异常 - 它只是由于内存不足而导致的段错误我猜.

我使用了 valgrind,但它只发现了一次小泄漏,没有别的。我也尝试过 gdb,但尽管应用程序是使用 -g -rdynamic 标志编译的,但它并没有将所有地址转换为函数名称。

你能告诉我一些更好的内存调试方法,我可以用它们来确定泄漏的来源吗?

【问题讨论】:

  • 分段错误通常不是由于缺少内存;它们的发生是因为以错误的方式访问内存(取消引用 Wild、null 或已删除的指针)或管理不善(双重删除、删除 []/删除不匹配等)。错误并不总是出现在错误点,因为可能会损坏内存,导致程序稍后失败。

标签: c++ linux memory memory-management memory-leaks


【解决方案1】:

Valgrind 在发现泄漏方面通常非常可靠,所以你确定这是内存泄漏吗?

堆分析器可以帮助您查看正在创建的对象以及它们是否是您所期望的。 Massif 就是这样一种可能被证明有用的工具。

【讨论】:

    【解决方案2】:

    C++ 术语中的“内存泄漏”是指尚未释放但不再可访问的孤立内存。如果 valgrind 说您没有泄漏,那么您可能保留了指向不再需要的对象的指针。严格来说,这不是泄漏,但它最终会导致您的内存使用量激增。

    如果您想使用 valgrind,请传递 --show-reachable 标志,这将在您的应用退出时转储内存中仍可访问的所有对象。然后您可以查看这些堆栈跟踪并确定哪些对象在内存中保留时间过长以及原因。

    【讨论】:

      【解决方案3】:

      正如其他人所指出的,这可能不是一个简单的泄漏。更有可能是错误的强制转换,这使得它误解了某些对象的类型。或者缓冲区下溢/溢出,或者整数翻转(一些 32 位有符号偏移量超过 2Gig?),或者悬空指针......

      根据我的经验,当您构建复杂的结构时,到处都是指针,您需要结构的正式规范。特别重要的是一组不变性。有了这些,您就可以同时构建一个测试套件和一个运行时验证器,以确保您的数据仍然是一致且整洁的。

      【讨论】:

        【解决方案4】:

        我建议您首先尝试使用 gdb 解决您的问题,因为它是找出发生段错误时会发生什么的第一工具。然后运行你的程序直到它崩溃,并确保系统生成一个核心文件(使用ulimit -c unlimited允许创建一个核心文件,如果它是一个守护进程要小心,它必须为实际运行的用户完成守护进程)。此时您可以将 gdb 与核心文件一起使用来找出段错误发生的位置(参见。backtrack 命令)。

        【讨论】:

          【解决方案5】:

          这也可能是堆栈溢出(当然这很奇怪,但它也可能适合您的所有问题)。例如,如果某个函数在一段时间后(隐式或显式)调用自身,则可能会发生这种情况。我再说一遍,这将是一个奇怪且非常罕见的问题,但这是我在阅读所有答案和问题后想到的。

          【讨论】:

            【解决方案6】:

            Valgrind 可能不擅长的一件事是在线程应用程序中发现漏洞。如果您的泄漏是竞争条件的结果,它会在调试期间消失,因为 Valgrind 会序列化所有内容。

            我调试过的几乎每一个“泄漏”,尤其是在 Java 中,都是标准集合不受限制地增长的结果。即永远不会被清理的向量,超出预期的字典等等。如果 Valgrind 没有找到任何东西,很有可能它不是真正的泄漏。

            【讨论】:

            • 但是如果程序没有竞争条件,那会是个问题吗?如果不是,也许 OP 应该开始解决这个问题
            • 这不是问题,但有时在 Valgrind 中成功通过可以作为一个指标。除了性能之外,单线程服务器永远不会产生副作用。
            【解决方案7】:

            您是否从编译器或链接器收到任何奇怪的警告?有什么与 libstdc++ 相关的吗?我们遇到了一个问题,我们同时链接到两个不同版本的 libstdc++(5 和 6),这给了我们可怕的内存泄漏。

            【讨论】:

              【解决方案8】:

              我读过一次,如果内存不足,有时 new 会返回 NULL,而不是抛出异常。也许这导致了段错误?

              【讨论】:

                猜你喜欢
                • 2011-08-24
                • 1970-01-01
                • 2012-07-06
                • 2011-03-13
                • 2015-05-09
                • 2021-03-28
                • 2020-12-19
                • 2011-04-01
                相关资源
                最近更新 更多