该块中提到的所有功能都是库函数.我怎样才能纠正这个内存泄漏?
它列在" 仍可达 "类别下.(还有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)
Run Code Online (Sandbox Code Playgroud)
Catch:一旦我运行我的程序,它没有内存泄漏,但它在Valgrind输出中有一个额外的行,之前没有出现:
由于munmap()而丢弃/lib/libgcc_s-4.4.4-20100630.so.1中的0x5296fa0-0x52af438处的syms
如果泄漏无法纠正,有人可以解释为什么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);
}
Run Code Online (Sandbox Code Playgroud)
运行:
valgrind -v --leak-check=full --show-reachable=yes ./a.out
Run Code Online (Sandbox Code Playgroud)
Dan*_*ing 353
定义"内存泄漏"的方法不止一种.特别是,程序员通常使用"内存泄漏"的两个主要定义.
"内存泄漏"的第一个常用定义是"内存已分配,并且在程序终止之前未被释放".然而,许多程序员(正确地)认为符合这个定义的某些类型的内存泄漏实际上并没有造成任何问题,因此不应该被认为是真正的 "内存泄漏".
"内存泄漏"的一个可以说更严格(也更有用)的定义是,"内存已分配,随后无法释放,因为程序不再有指向已分配内存块的指针." 换句话说,你不能释放你不再有任何指针的记忆.因此,这种存储器是"存储器泄漏".Valgrind使用了"内存泄漏"一词的更严格定义.这种泄漏类型可能会导致严重的堆耗尽,特别是对于长寿命流程.
Valgrind泄漏报告中的"仍可达"类别是指仅适用于"内存泄漏"的第一个定义的分配.这些块没有被释放,但它们本可以被释放(如果程序员想要的话),因为程序仍然跟踪指向那些内存块的指针.
通常,不需要担心"仍然可以访问"的块.它们不会造成真正的内存泄漏可能导致的问题.例如,"仍然可以访问"的块通常没有堆耗尽的可能性.这是因为这些块通常是一次性分配,在过程的整个生命周期中都会保留对它们的引用.虽然您可以通过并确保您的程序释放所有已分配的内存,但这样做通常没有任何实际好处,因为操作系统将在进程终止后回收所有进程的内存,无论如何.将此与真实对比 内存泄漏,如果保持不固定状态,如果运行时间过长,可能会导致进程耗尽内存,或者只会导致进程占用的内存远远超过必要的内存.
可能唯一一次确保所有分配都具有匹配的"释放"是唯一的时间,如果您的泄漏检测工具无法判断哪些块"仍然可以访问"(但Valgrind可以执行此操作),或者您的操作系统没有回收所有分配终止进程的内存(Valgrind已经移植到所有平台上执行此操作).
Jen*_*edt 10
由于底层的pthread系列有一些例程(但我不知道那个特定的例程),我的猜测是你已经启动了一些已经终止执行的可连接线程.
在您致电之前,该线程的退出状态信息将保持可用pthread_join
.因此,内存在程序终止时保存在丢失记录中,但由于您可以使用pthread_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
Run Code Online (Sandbox Code Playgroud)
因为这个dl-
东西类似于你看到的很多东西,我想你会看到一个已知的问题,它有一个抑制文件的解决方案valgrind
.也许您的系统不是最新的,或者您的发行版不保留这些内容.(我的是ubuntu 10.4,64bit)
你似乎不明白是什么still reachable
意思.
什么still reachable
是不泄漏.你不需要做任何事情.
小智 6
这是“仍然可以访问”的正确解释:
“仍然可达”是分配给全局和静态局部变量的泄漏。由于 valgrind 跟踪全局变量和静态变量,因此它可以排除分配“一劳永逸”的内存分配。一个全局变量分配了一次分配并且从未重新分配该分配通常不是“泄漏”,因为它不会无限期地增长。从严格意义上讲,它仍然是泄漏,但通常可以忽略,除非您迂腐。
分配了分配而不是释放的局部变量几乎总是泄漏。
这是一个例子
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);
....
....
....
}
Run Code Online (Sandbox Code Playgroud)
Valgrind 会将working_buf 报告为“仍可到达- 16k”,将temp_buf 报告为“肯定丢失- 5k”。