仍然可达的泄漏检测瓦尔格林

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

它被列在“ 还能联系上”类别下。(还有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)

当我运行我的程序时,它没有给出任何内存泄漏,但是它有一个额外的行出现在 Val弓输出中,这在以前是不存在的:

丢弃0x5296fa0-0x52af438的系统 在/lib/libgcc _ s-4.4.4-20100630.so. 1 因为 munmap ()

如果泄漏不能得到纠正,那么至少有人可以解释一下为什么 munmap ()线导致 Valgrind 报告0“仍然可到达”的泄漏?

编辑:

下面是一个最小的测试样本:

#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
147537 次浏览

你好像不明白 still reachable是什么意思。

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

由于底部有一些来自 pthread 家族的例程(但是我不知道那个特定的例程) ,我猜测您已经启动了一些线程,它们已经终止了执行。

在调用 pthread_join之前,该线程的退出状态信息是可用的。因此,内存在程序终止时保存在丢失记录中,但是仍然可以访问,因为可以使用 pthread_join访问它。

如果这个分析是正确的,要么启动这些分离的线程,要么在终止程序之前加入它们。

Edit : 我运行了您的示例程序(经过一些明显的更正) ,没有错误,但是出现了以下错误

==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。也许您的系统没有更新,或者您的发行版没有维护这些东西。(我的是 ubuntu 10.4,64位)

定义“内存泄漏”的方法不止一种。特别是,“内存泄漏”有两个主要定义,它们在程序员中很常见。

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

“内存泄漏”的一个可以说更严格(也更有用)的定义是,“内存被分配,随后 不能被释放,因为程序不再有任何指向已分配内存块的指针。”换句话说,您不能释放不再有任何指针指向的内存。因此,这样的内存是“内存泄漏”。瓦尔恩对“内存泄漏”这个术语使用了更严格的定义。这种类型的泄漏可能会导致显著的堆消耗,特别是对于长期存在的进程。

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

一般来说,不需要担心“仍然可到达”的块。它们不会造成 没错内存泄漏可能导致的那种问题。例如,“仍然可到达”的块通常不可能耗尽堆。这是因为这些块通常是一次性分配,对它们的引用将在整个流程生命周期中保留。虽然您可以通过并确保您的程序释放 所有分配的内存,但这样做通常没有实际好处,因为操作系统将在进程终止后回收所有进程的内存。与此形成对比的是 没错内存泄漏,如果不进行修复,如果保持足够长的运行时间,就可能导致进程耗尽内存,或者只会导致进程消耗远远超过必要的内存。

确保所有分配都有匹配的“空闲”可能是唯一有用的时候,如果您的泄漏检测工具不能告诉哪些块是“仍然可以访问的”(但瓦尔恩可以做到这一点) ,或者如果您的操作系统没有回收一个终止进程的所有内存(所有瓦尔恩已经被移植来做这件事的平台)。

以下是对“仍然可以联系到”的恰当解释:

“仍然可达”是指分配给全局变量和静态局部变量的泄漏。因为 valgray 跟踪全局变量和静态变量,所以它可以排除分配给“一次性忘记”的内存分配。一个全局变量分配了一次分配,并且从未重新分配该分配,从它不会无限增长的意义上来说,这通常不是一个“泄漏”。在严格意义上,它仍然是一个漏洞,但通常可以忽略,除非你是迂腐的。

分配了分配而没有释放的局部变量几乎总是泄漏。

这里有一个例子

int foo(void)
{
static char *working_buf = NULL;
char *temp_buf;
if (!working_buf) {
working_buf = (char *) malloc(16 * 1024);
}
temp_buf = (char *) malloc(5 * 1024);


....
....
....


}

瓦尔恩将把 working _ buf 报告为“仍然可达 -16k”,而将 temp _ buf 报告为“绝对丢失 -5k”。

对于未来的读者,“仍然可以访问”可能意味着您忘记关闭文件之类的东西。虽然在最初的问题中看起来不是这样,但是你应该总是确保你已经这样做了。