Valgrind - 在共享库中查找内存泄漏

13

我需要知道如何找出在一个共享库中的内存泄漏,该共享库将被加载到一个发布二进制文件中。我的意思是,我使用了-g选项来构建共享库,但是加载共享库的二进制文件没有使用-g选项进行构建。

我得到的泄漏报告如下所示。

==739==    at 0x4A05809: malloc (vg_replace_malloc.c:149)
==739==    by 0x84781B1: ???
==739==    by 0x87507F5: ???
==739==    by 0x874CF47: ???
==739==    by 0x874E657: ???
==739==    by 0x874F7C2: ???
==739==    by 0x8779C0C: ???
请告诉我如何从共享库中获取泄漏的堆栈跟踪?

我发帖是为了帮助那些在 valgrind 输出中看到 ??(问号)的人——确保你尝试不同版本的 valgrind。我使用了另一个版本的 valgrind,所有那些 ?? 都消失了。 - Mohit
2个回答

10

假设漏洞确实是来自您的共享库,那么我认为问题不在于主可执行文件缺少调试。

更可能的是,可执行文件在完成前调用 dlclose 卸载了共享库。这意味着当 Valgrind 来检查内存泄漏时,所有库的符号信息都已经不存在了,因为该库已经没有被加载。

如果您可以重建可执行文件,则最简单的解决方案可能是暂时停止它调用 dlclose,以便库保持加载状态直到结束。

如果无法这样做,请尝试使用 LD_PRELOAD 使库保持加载状态,像这样:

LD_PRELOAD="/path/to/library.so" valgrind my-executable

希望这可以欺骗动态链接器,使库在关闭后仍然保持加载状态。


有一个补丁提供了一个选项,可以在dlclose之后禁用符号卸载。这个补丁有效,我已经使用过很多次。但是这个补丁是在旧版本上的,我猜现在已经过时了。https://bugs.kde.org/show_bug.cgi?id=79362 - k0n3ru
@TomH:让我指出,“省略dlclose”解决方法可能会导致大量的误报。如果堆栈上有销毁堆中元素的对象,则这些对象在输出中显示为泄漏,因为dlclose本来就会首先执行销毁操作。 - newhouse
第二个也不起作用,如果valgrind是64位的,但你调试32位的。 - newhouse

4

正如前面的答案所建议的那样,这是因为在程序终止之前关闭了库,因此符号信息对valgrind不可用。

使用LD_PRELOAD对我没有起作用;现在我有两个版本的构建;其中一个明确地不调用dlclose();在这个版本上,valgrind正确地报告了行号信息,就像动态链接一样。


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