尽管进行了 atexit 清理,valgrind --trace-children=yes 仍报告泄漏 [英] valgrind --trace-children=yes reports leak despite atexit cleanup

查看:86
本文介绍了尽管进行了 atexit 清理,valgrind --trace-children=yes 仍报告泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 valgrind 避免误报,但我对 atexit()fork() 的组合感到很糟糕,尽管使用了 --trace-children=yes.我的代码:

I'm trying to avoid false positives with valgrind, but I'm suck with a combination of atexit() and fork(), despite using --trace-children=yes. My code:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

static int * arr;

static void cleanup() {
    free(arr);
    printf("free arr as: %p\n", (void *)arr);
}

int main()
{
    arr = malloc(16 * sizeof(int));
    printf("allocated arr as: %p\n", (void *)arr);
    atexit(cleanup);

    pid_t pid = fork();
    if (pid == -1) {
        exit(1);
    } else if (pid == 0) {
        // child
        _exit(0);
    } else {
        // parent
        exit(0);
    }
}

命令行:

$ clang -Weverything leak.c 
$ valgrind --trace-children=yes ./a.out 
==3287== Memcheck, a memory error detector
==3287== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3287== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==3287== Command: ./a.out
==3287== 
allocated arr as: 0x5202040
free arr as: 0x5202040
==3288== 
==3288== HEAP SUMMARY:
==3288==     in use at exit: 64 bytes in 1 blocks
==3288==   total heap usage: 2 allocs, 1 frees, 1,088 bytes allocated
==3288== 
==3288== LEAK SUMMARY:
==3288==    definitely lost: 0 bytes in 0 blocks
==3288==    indirectly lost: 0 bytes in 0 blocks
==3288==      possibly lost: 0 bytes in 0 blocks
==3288==    still reachable: 64 bytes in 1 blocks
==3288==         suppressed: 0 bytes in 0 blocks
==3288== Rerun with --leak-check=full to see details of leaked memory
==3288== 
==3288== For counts of detected and suppressed errors, rerun with: -v
==3288== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==3287== 
==3287== HEAP SUMMARY:
==3287==     in use at exit: 0 bytes in 0 blocks
==3287==   total heap usage: 2 allocs, 2 frees, 1,088 bytes allocated
==3287== 
==3287== All heap blocks were freed -- no leaks are possible
==3287== 
==3287== For counts of detected and suppressed errors, rerun with: -v
==3287== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

根据 printf() 输出,看起来没有泄漏.我可以让 valgrind 相信这一点,还是应该将其添加到我的 valgrind 抑制文件中?

Based on the printf() output, it looks like there's no leaks. Can I convince valgrind of this, or should I just add this to my valgrind suppression file?

推荐答案

根据 printf() 输出,看起来没有泄漏.我可以让 valgrind 相信这一点,还是应该将其添加到我的 valgrind 抑制文件中?

Based on the printf() output, it looks like there's no leaks. Can I convince valgrind of this, or should I just add this to my valgrind suppression file?

看来 valgrind 是对的.如果您将 printf() 输出解释为表明没有泄漏,那么您就没有意识到 fork() 的效果.

It appears that valgrind is right. If you interpret the printf() output as indicating that there are no leaks, then you're not appreciating the effect of fork().

当您 fork 一个孩子时,它会获得其父级地址空间的完整副本.这通常是通过写时复制页面实现的,但它仍然构成了属于孩子的内存.在您的情况下,这包括动态分配数组 arr 的副本.

When you fork a child, it gets a complete copy of its parent's address space. This is typically implemented via copy-on-write pages, but it still constitutes memory belonging to the child. In your case, that includes a copy of dynamically-allocated array arr.

子进程通过调用 _exit() 退出,因此尽管它继承了其父进程的退出处理程序注册,但在该进程中不会调用已注册的退出处理程序.您可以这么说是因为您只看到了 cleanup() 的输出一次.因此,正如 valgrind 告诉您的那样,属于孩子的 arr 副本永远不会被释放.

The child exits by calling _exit(), so although it inherits its parent's exit-handler registrations, registered exit handlers are not called in that process. You can tell that is so because you see the output of cleanup() only once. As a result, the copy of arr belonging to the child is never freed, as valgrind tells you.

不过,将其称为内存泄漏有点迂腐.当程序终止时,有问题的内存仍然可以访问,此时它会被系统回收.它只是在终止前没有显式释放.

It's a bit pedantic to call this a memory leak, though. The memory in question is still reachable when the program terminates, at which time it gets reclaimed by the system. It simply is not explicitly freed before termination.

这篇关于尽管进行了 atexit 清理,valgrind --trace-children=yes 仍报告泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆