C语言 Valgrind 检测到仍可到达的泄漏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3840582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:34:29  来源:igfitidea点击:

Still Reachable Leak detected by Valgrind

cpthreadsvalgrind

提问by Dan Moulding

All the functions mentioned in this block are library functions. How can I rectify this memory leak?

本块中提到的所有函数都是库函数。我怎样才能纠正这个内存泄漏?

It is listed under the "Still reachable" category. (There are 4 more, which are very similar, but of varying sizes)

它列在“仍然可达”类别下。(还有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:Once I ran my program, it gave no memory leaks, but it had one additional line in the Valgrind output, which wasn't present before:

Catch:一旦我运行了我的程序,它就没有出现内存泄漏,但它在 Valgrind 输出中多了一行,这在以前是不存在的:

Discarding syms at 0x5296fa0-0x52af438 in /lib/libgcc_s-4.4.4-20100630.so.1 due to munmap()

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

If the leak can't be rectified, can someone atleast explain why the munmap() line causes Valgrind to report 0 "still reachable" leaks?

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

Edit:

编辑:

Here's a minimal test sample:

这是一个最小的测试样本:

#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 with:

运行:

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

回答by Dan Moulding

There is more than one way to define "memory leak". In particular, there are two primary definitions of "memory leak" that are in common usage among programmers.

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

The first commonly used definition of "memory leak" is, "Memory was allocated and was not subsequently freed before the program terminated." However, many programmers (rightly) argue that certain types of memory leaks that fit this definition don't actually pose any sort of problem, and therefore should not be considered true"memory leaks".

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

An arguably stricter (and more useful) definition of "memory leak" is, "Memory was allocated and cannotbe subsequently freed because the program no longer has any pointers to the allocated memory block." In other words, you cannot free memory that you no longer have any pointers to. Such memory is therefore a "memory leak". Valgrind uses this stricter definition of the term "memory leak". This is the type of leak which can potentially cause significant heap depletion, especially for long lived processes.

“内存泄漏”的一个可以说更严格(也更有用)的定义是,“内存已分配,随后无法释放,因为程序不再有任何指向已分配内存块的指针。” 换句话说,您无法释放不再有任何指针指向的内存。因此,这种内存是“内存泄漏”。Valgrind 对术语“内存泄漏”使用了这个更严格的定义。这种泄漏可能会导致显着的堆耗尽,尤其是对于长期存在的进程。

The "still reachable" category within Valgrind's leak report refers to allocations that fit only the first definition of "memory leak". These blocks were not freed, but they could have been freed (if the programmer had wanted to) because the program still was keeping track of pointers to those memory blocks.

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

In general, there is no need to worry about "still reachable" blocks. They don't pose the sort of problem that truememory leaks can cause. For instance, there is normally no potential for heap exhaustion from "still reachable" blocks. This is because these blocks are usually one-time allocations, references to which are kept throughout the duration of the process's lifetime. While you could go through and ensure that your program frees allallocated memory, there is usually no practical benefit from doing so since the operating system will reclaim all of the process's memory after the process terminates, anyway. Contrast this with truememory leaks which, if left unfixed, could cause a process to run out of memory if left running long enough, or will simply cause a process to consume far more memory than is necessary.

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

Probably the only time it is useful to ensure that all allocations have matching "frees" is if your leak detection tools cannot tell which blocks are "still reachable" (but Valgrind can do this) or if your operating system doesn't reclaim all of a terminating process's memory (all platforms which Valgrind has been ported to do this).

确保所有分配具有匹配的“释放”可能唯一有用的时候是如果您的泄漏检测工具无法判断哪些块“仍然可以访问”(但 Valgrind 可以做到这一点)或者如果您的操作系统没有回收所有终止进程的内存(Valgrind 已被移植来执行此操作的所有平台)。

回答by Jens Gustedt

Since there is some routine from the the pthread family on the bottom (but I don't know that particular one), my guess would be that you have launched some thread as joinable that has terminated execution.

由于底部有一些来自 pthread 系列的例程(但我不知道那个特定的例程),我猜测您已经启动了一些已终止执行的可连接线程。

The exit state information of that thread is kept available until you call pthread_join. Thus, the memory is kept in a loss record at program termination, but it is still reachable since you could use pthread_jointo access it.

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

If this analysis is correct, either launch these threads detached, or join them before terminating your program.

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

Edit: I ran your sample program (after some obvious corrections) and I don't have errors but the following

编辑:我运行了您的示例程序(经过一些明显的更正后)并且我没有错误,但是以下内容

==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

Since the dl-thing resembles much of what you see I guess that you see a known problem that has a solution in terms of a suppression file for valgrind. Perhaps your system is not up to date, or your distribution doesn't maintain these things. (Mine is ubuntu 10.4, 64bit)

由于这dl-件事与您看到的大部分内容相似,我猜您看到了一个已知问题,该问题在valgrind. 也许你的系统不是最新的,或者你的发行版没有维护这些东西。(我的是 ubuntu 10.4,64 位)

回答by Employed Russian

You don't appear to understand what still reachablemeans.

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

Anything still reachableis nota leak. You don't need to do anything about it.

什么still reachable泄漏。你不需要做任何事情。

回答by Abbey Road

Here is a proper explanation of "still reachable":

这是“仍然可以访问”的正确解释:

"Still reachable" are leaks assigned to global and static-local variables. Because valgrind tracks global and static variables it can exclude memory allocations that are assigned "once-and-forget". A global variable assigned an allocation once and never reassigned that allocation is typically not a "leak" in the sense that it does not grow indefinitely. It is still a leak in the strict sense, but can usually be ignored unless you are pedantic.

“仍然可达”是分配给全局和静态局部变量的泄漏。由于 valgrind 跟踪全局变量和静态变量,因此它可以排除分配“一劳永逸”的内存分配。一个全局变量分配了一次分配并且从未重新分配该分配通常不是“泄漏”,因为它不会无限期地增长。从严格意义上讲,它仍然是泄漏,但通常可以忽略,除非您迂腐。

Local variables that are assigned allocations and not free'd are almost always leaks.

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

Here is an example

这是一个例子

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 will report working_buf as "still reachable - 16k" and temp_buf as "definitely lost - 5k".

Valgrind 会将working_buf 报告为“仍可到达- 16k”,将temp_buf 报告为“肯定丢失- 5k”。

回答by MonerosKin

For future readers, "Still Reachable" might mean you forgot to close something like a file. While it doesn't seem that way in the original question, you should always make sure you've done that.

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