Valgrind检测到仍然可达泄漏

所有在这个块中提到的函数都是库函数。 我该如何纠正这个内存泄漏?

它列在“ 可到达 ”类别下。 (还有4个,非常相似,但大小不一)

630 bytes in 1 blocks are still reachable in loss record 5 of 5 at 0x4004F1B: calloc (vg_replace_malloc.c:418) by 0x931CD2: _dl_new_object (dl-object.c:52) by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972) by 0x92EFB6: _dl_map_object (dl-load.c:2251) by 0x939F1B: dl_open_worker (dl-open.c:255) by 0x935965: _dl_catch_error (dl-error.c:178) by 0x9399C5: _dl_open (dl-open.c:584) by 0xA64E31: do_dlopen (dl-libc.c:86) by 0x935965: _dl_catch_error (dl-error.c:178) by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47) by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53) by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 

Catch:一旦我运行我的程序,它没有发生内存泄漏,但在Valgrind输出中还有一行,之前没有:

由于munmap()在/lib/libgcc_s-4.4.4-20100630.so.1中的0x5296fa0-0x52af438丢弃syms

如果泄漏无法纠正,有人可以解释为什么munmap()行会导致Valgrind报告0“仍然可达”泄漏?

编辑:

这是一个最小的testing样本:

 #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *runner(void *param) { /* some operations ... */ pthread_exit(NULL); } int n; int main(void) { int i; pthread_t *threadIdArray; n=10; /* for example */ threadIdArray = malloc((n+n-1)*sizeof(pthread_t)); for(i=0;i<(n+n-1);i++) { if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) { printf("Couldn't create thread %d\n",i); exit(1); } } for(i=0;i<(n+n-1);i++) { pthread_join(threadIdArray[i],NULL); } free(threadIdArray); return(0); } 

运行:

 valgrind -v --leak-check=full --show-reachable=yes ./a.out 

有多种方法来定义“内存泄漏”。 特别是程序员通常使用的“内存泄漏”有两个主要的定义。

“内存泄漏”的第一个常用定义是“内存已分配,并且在程序终止之前未被释放”。 然而,许多程序员(正确地)认为,符合这个定义的某些types的内存泄漏实际上不会造成任何问题,因此不应该被认为是真正的 “内存泄漏”。

可以说更严格的(更有用的)“内存泄漏”的定义是,“内存被分配, 不能被释放,因为程序不再有任何指向分配内存块的指针”。 换句话说,你不能释放内存,你不再有任何指针。 这样的记忆因此是一个“内存泄漏”。 Valgrind使用这个更严格的术语“内存泄漏”的定义。 这是可能导致重大堆耗尽的泄漏types,特别是对于长期存在的过程。

Valgrind的泄漏报告中的“可到达”类别是指仅适合“内存泄漏”的第一个定义的分配。 这些块没有被释放,但它们本来可以被释放(如果程序员想要的话),因为程序仍然跟踪指向这些存储块的指针。

一般来说,没有必要担心“可到达”块。 它们不会造成真正的内存泄漏可能导致的问题。 例如,从“可到达”块中堆通常没有潜在的枯竭。 这是因为这些块通常是一次性分配,在整个过程的整个生命周期中都保留对这些分配的引用。 虽然可以通过并确保程序释放所有分配的内存,但是这样做通常没有实际的好处,因为操作系统在进程终止后将收回所有进程的内存。 将其与真正的内存泄漏相比较,如果不加固定的话,如果运行时间足够长,可能会导致进程内存不足,或者只会导致进程占用的内存超过必要的内存。

如果你的泄漏检测工具不能确定哪些块是“可到达的”(但Valgrind可以做到这一点),或者如果你的操作系统没有收回所有的分配块终止进程的内存(Valgrind已经移植到所有平台)。

由于底层的pthread系列有一些例程(但我不知道这个例子),我猜测你已经启动了一些线程作为可连接的终止执行。

该线程的退出状态信息保持可用,直到您调用pthread_join 。 因此,内存在程序终止时保存在一个丢失logging中,但是它仍然可以访问,因为你可以使用pthread_join来访问它。

如果这种分析是正确的,可以启动这些脱pipe的线程,或者在终止你的程序之前join它们。

编辑 :我跑你的示例程序(经过一些明显的更正),我没有错误,但以下

 ==18933== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) --18933-- --18933-- used_suppression: 2 dl-hack3-cond-1 --18933-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a 

由于dl-事与你所看到的很相似,所以我想你会发现一个已知的问题,在valgrind的压缩文件方面有一个解决scheme。 也许你的系统不是最新的,或者你的发行版不能维护这些东西。 (我的是Ubuntu 10.4,64bit)

你似乎不明白什么still reachable意思。

任何still reachable东西都不是泄漏。 你不需要做任何事情。