Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Valgrind检测到仍然可以到达的泄漏_C_Pthreads_Valgrind - Fatal编程技术网

C Valgrind检测到仍然可以到达的泄漏

C Valgrind检测到仍然可以到达的泄漏,c,pthreads,valgrind,C,Pthreads,Valgrind,此块中提到的所有函数都是库函数。如何更正此内存泄漏 它列在“仍然可以访问”类别下。(还有4个,非常相似,但大小不一) 捕获:一旦我运行了我的程序,它就没有内存泄漏,但在Valgrind输出中有一行额外的内容,这是以前没有的: 丢弃0x5296fa0-0x52af438处的符号 in/lib/libgcc_-4.4.4-20100630.so.1 由于munmap() 如果泄漏无法纠正,至少有人能解释为什么munmap()行导致Valgrind报告0“仍然可以到达”泄漏吗 编辑: 这是一个最小的测

此块中提到的所有函数都是库函数。如何更正此内存泄漏

它列在“仍然可以访问”类别下。(还有4个,非常相似,但大小不一)

捕获:一旦我运行了我的程序,它就没有内存泄漏,但在Valgrind输出中有一行额外的内容,这是以前没有的:

丢弃0x5296fa0-0x52af438处的符号 in/lib/libgcc_-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);
}

您似乎不明白什么是仍然可以访问的
意思


任何仍然可以到达的
都不是泄漏。您不需要对此做任何事情。

因为底部有一些来自pthread家族的例程(但我不知道是哪一个),我猜您已经启动了一些线程作为可连接线程,并终止了执行

在调用
pthread\u join
之前,该线程的退出状态信息一直可用。因此,在程序终止时,内存保存在丢失记录中,但它仍然可以访问,因为您可以使用
pthread\u 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
的抑制文件。也许您的系统不是最新的,或者您的发行版没有维护这些东西。(我的是ubuntu 10.4,64位)

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

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

“内存泄漏”的一个可能更严格(也更有用)的定义是,“内存已分配,并且无法随后释放,因为程序不再有指向已分配内存块的指针。”换句话说,您无法释放不再有指向该块指针的内存。因此,这种内存是“内存泄漏”。Valgrind对“内存泄漏”一词使用了更严格的定义。这是一种可能导致大量堆耗尽的泄漏类型,特别是对于长寿命进程

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

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


确保所有分配都具有匹配的“空闲”可能唯一有用的时间是泄漏检测工具无法判断哪些块“仍然可以访问”(但Valgrind可以做到这一点),或者操作系统没有回收终止进程的所有内存(Valgrind已移植用于此操作的所有平台).

以下是对“仍然可以到达”的正确解释:

“仍然可到达”是指分配给全局和静态局部变量的泄漏。因为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);

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

}

Valgrind将报告working_buf为“仍然可以访问-16k”,temp_buf为“绝对丢失-5k”。

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

你能猜出munmap()是做什么使“仍然可以到达”的块消失的吗?@crypto:可能是卸载共享对象后调用了
munmap
。共享对象使用的所有资源可能在卸载之前都已释放。这可以解释为什么在
munmap
案例中“仍然可以到达”被释放。不过,我只是在猜测。这里没有足够的信息可以确定。在一种情况下,“仍然可以访问”的内存可以被视为内存泄漏:假设您
==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
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);

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

}