valgrind报告dlopen中的内存泄漏?

19

最近我用valgrind调试了一些应用程序,但从dlopen中得到的报告非常奇怪。

==1987== 32 bytes in 1 blocks are still reachable in loss record 1 of 2
==1987==    at 0x4C24477: calloc (vg_replace_malloc.c:418)
==1987==    by 0x570F31F: _dlerror_run (dlerror.c:142)
==1987==    by 0x570EEE0: dlopen@@GLIBC_2.2.5 (dlopen.c:88)
        <my call to dlopen>
==1987==
==1987== 264 bytes in 1 blocks are still reachable in loss record 2 of 2
==1987==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==1987==    by 0x400CD44: _dl_map_object_deps (dl-deps.c:506)
==1987==    by 0x4012DA2: dl_open_worker (dl-open.c:326)
==1987==    by 0x400E385: _dl_catch_error (dl-error.c:178)
==1987==    by 0x40126C6: _dl_open (dl-open.c:615)
==1987==    by 0x570EF65: dlopen_doit (dlopen.c:67)
==1987==    by 0x400E385: _dl_catch_error (dl-error.c:178)
==1987==    by 0x570F2AB: _dlerror_run (dlerror.c:164)
==1987==    by 0x570EEE0: dlopen@@GLIBC_2.2.5 (dlopen.c:88)
        <my call to dlopen>

这看起来像是为dlerror初始化的错误消息,但查看手册页面,它没有说明如何清除此消息。有什么想法可以正确地摆脱它吗?


是的,当然,我已经仔细检查了dlclose是否被正确调用 - 但仅在dlopen返回值!= NULL时才调用,我怀疑这是因为dlopen返回0的情况。 - Anteru
3个回答

14

使用一些“hello world”代码复现了这个问题,甚至没有调用任何已加载对象中的符号。 http://pastebin.com/d690bea57

我认为这是libc或valgrind中的一个bug。 可以在Ubuntu 9.04和Scientific Linux 5.3上重现(分别为20和32个字节)。

编辑(由Calmarius完成):

这个简单代码可以复现问题:

#include <dlfcn.h>

int main()
{
    void* handle = 0;

    handle = dlopen("libm.so", RTLD_NOW);
    dlclose(handle);    

    return 0;
}

当使用此命令进行编译时:

gcc -Wl,--no-as-needed -g -o stuff  main.c -ldl -lpthread

即使是最新的valgrind 3.11在Ubuntu 14.04上也能重现这个问题。

已经提交了上游错误报告:https://bugs.kde.org/show_bug.cgi?id=358980


一位朋友指出这是Valgrind中的一个bug。 https://issues.asterisk.org/view.php?id=16007 请查看附加的Valgrind抑制文件。 - Aram Verstegen
5
如果你的代码以pthread_exit(NULL)结束,即使你没有使用pthread,valgrind也不会报告这个泄漏。也许这能帮助某些人,这可能比编写一个valgrind抑制文件更简单。 - Aram Verstegen
我假设调用pthread_exit会清理线程本地存储器,该存储器用于存储错误文本(以便它是多线程安全的--您只需要在调用dlopen和dlerror之间保持线程亲和性)。 - KayEss
3
-1 是因为粘贴板上的内容消失了。(否则我会将其编辑到答案中……) - SamB
问题在Ubuntu 20.04.4 LTS和valgrind-3.15.0下也可以重现。 - Johannes Overmann

4
这个抑制效果更好:
{
   Ignore dlopen bug.
   Memcheck:Leak
   ...
   fun:_dl_open
   ...
}

(请注意,“...”是省略号的一部分,应该直接输入。)
(注意:“…”是抑制的一部分,应该直接输入。)

1

我在各种库中都看到过这种情况,无论是使用dlopen还是不使用。我只是假设这是库内部的一些神奇实现方式欺骗了valgrind - 或者 - 这些库确实存在内存泄漏,那么在我的应用程序中就无法做任何事情。


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