检测在退出时被释放的C语言内存“泄漏”问题。

5
假设我有一个在Linux下运行的C程序,它操作许多数据结构,其中一些是复杂的,几个可以增长和缩小,但通常不应该增长。这个程序被观察到随着时间的推移而逐渐增加RSS(比内存碎片化更多)。我想找出哪里出现了泄漏。在这里,运行valgrind是显而易见的建议,但是valgrind(使用--leak-check=full--show-reachables=yes)没有显示任何泄漏。我认为这是因为数据结构本身在退出时被正确释放,但其中一个正在程序的生命周期中增长。例如,可能会有一个链表,它随着时间的推移呈线性增长,有人忘记从列表中删除资源,但退出清理在退出时正确地释放了所有列表项。当然,如果它们被释放,这是否实际上是“泄漏”是一个哲学问题(因此问题中有引号)。
有什么有用的工具来检测这个问题吗?我希望能够在valgrind下运行,并像在退出时一样生成当前分配报告,但要在信号下发生并允许程序继续。然后,我可以查找哪些堆栈跟踪签名具有不断增长的分配。
我可以可靠地从gdb生成一个很好的大型“core”文件;如果我使用了一个方便的malloc()调试库来对malloc()进行插装,是否有一种离线分析它的方法?
我完全可以访问源代码,并且可以修改它,但我不想手动检测每个数据结构,而且我更感兴趣的是问题的通用解决方案(如valgrind提供的)而不是如何解决这个特定问题。
我在这里寻找类似的问题,但它们似乎都是:
- 我的程序为什么会泄漏内存? - 如何在退出时检测内存泄漏?(对我没有用) - 如何从核心文件中检测内存泄漏?(很好,但没有一个令人满意的答案)
如果我在Solaris下运行,我猜答案将是“使用这个方便的脚本”。

1
他只是对术语感到困惑。只要内存可访问,它就不会丢失或泄漏。请重新编写问题,并避免使用“泄漏”一词。这不是泄漏。 - Karoly Horvath
@abligh,请解释一下,当某个东西在退出时被释放时,它为什么会是一个“泄漏”? - Montaldo
@Montaldo,使用一个合理的定义(第一个谷歌搜索结果),“程序未释放废弃内存,导致性能下降或失败。” - 这就是正在发生的事情。请注意,在任何程序中,所有内存在退出时都会被释放(当页面取消映射时),并且直到页面取消映射为止,总会有一些东西(即使只有操作系统和malloc分配结构本身)引用该内存。因此,仅将泄漏的内存视为在退出时未通过调用free()释放的内容是太狭隘了。 - abligh
兄弟,我只能说你太理论化了。 - Karoly Horvath
2
生活会不会变得更容易,如果你把“泄漏”称作其他人在这个蓝色星球上都称之为“泄漏”的东西呢?我是不是太实用主义了? :) - Karoly Horvath
显示剩余4条评论
2个回答

5
Valgrind 包括一个 gdbserver。这意味着您可以使用 gdb 连接到它,例如发出泄漏转储或在运行时显示所有可达内存。当然,您必须判断是否存在“内存泄漏”,因为 Valgrind 无法知道应用程序逻辑中是否存在释放内存但仍保留引用的 bug。
使用 --vgdb=yes 标志运行 Valgrind,然后运行以下命令:
valgrind --vgdb=yes --leak-check=full --show-reachable=yes ./yourprogram 
gdb ./yourprogram
(gdb) target remote | vgdb
(gdb) monitor leak_check full reachable any

请参阅文档以获取更多信息,在这里在这里。您还可以在您的程序中以编程方式执行此操作。
#include <valgrind/memcheck.h>

并在代码的适当位置执行以下操作:

 VALGRIND_DO_LEAK_CHECK;
(如果使用--show-reachable=yes选项运行valgrind,它将显示可访问的内存)

谢谢 - 看起来非常有用,特别是VALGRIND_DO_ADDED_LEAK_CHECK。如果我能将输出保存到文件中,那就更好了,但我会自己试试看。 - abligh
你可以将stdout/stderr重定向到文件中,我相信gdb也有一些命令可以将输出保存到文件中。 - nos
我还没有尝试过,但我认为编程调用会出现在目标的STDERR上,不是吗?在这种情况下,它被定向到/dev/null(它是一个守护进程)。无论如何,这是一个微不足道的问题可以解决。 - abligh

1

有一个Valgrind Massif工具,它显示您的应用程序的总体内存使用情况,而不仅仅是泄漏的内存。它通过调用函数及其回溯来分解malloc()free(),因此您可以看到哪些函数在分配内存时没有释放它。这是一种非常好的工具,可以用于查找您提到的类型的泄漏。

不幸的是,与Massif有关的工具有点奇怪... Valgrind提供的ms_print工具仅适用于最基本的任务;对于实际工作,您可能需要使用一些显示图形的工具。网络上有几个这种工具,例如Valgrind Massif tool output graphical interface?


谢谢 - 也很有用。 - abligh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接