Valgrind:Valgrind 检测到仍然存在泄漏

发布于 2024-09-26 04:58:21 字数 1895 浏览 6 评论 0原文

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

它列在“仍然可达”类别下。 (还有另外 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 输出中多了一行,这是之前没有出现过:

丢弃 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

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)

 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:

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烟沫凡尘 2024-10-03 04:58:21

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

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

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

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

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

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

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 cannot be 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.

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.

In general, there is no need to worry about "still reachable" blocks. They don't pose the sort of problem that true memory 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 all allocated 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 true memory 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.

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).

最偏执的依靠 2024-10-03 04:58:21

这是“仍然可达”的正确解释:

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

分配分配但未释放的局部变量几乎总是泄漏。

下面是一个示例,

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

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

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.

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 = malloc(16 * 1024);
    }
    temp_buf = malloc(5 * 1024);
    ....
    ....
    ....
}

Valgrind will report working_buf as "still reachable - 16k" and temp_buf as "definitely lost - 5k".

会发光的星星闪亮亮i 2024-10-03 04:58:21

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

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.

亚希 2024-10-03 04:58:21

您似乎不明白 stillreachable 的含义。

任何仍然可达的东西都不是泄漏。你不需要对此做任何事情。

You don't appear to understand what still reachable means.

Anything still reachable is not a leak. You don't need to do anything about it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文