gpe*_*iva 5 c static valgrind memory-leaks atexit
我试图避免与Valgrind的误报,但我用的组合吸atexit()并fork(),尽管使用--trace-children=yes.我的代码:
#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);
}
}
Run Code Online (Sandbox Code Playgroud)
命令行:
$ 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)
Run Code Online (Sandbox Code Playgroud)
根据printf()输出,看起来没有泄漏.我可以说服valgrind这个,还是我应该把它添加到我的valgrind抑制文件中?
基于printf()输出,看起来没有泄漏.我可以说服valgrind这个,还是我应该把它添加到我的valgrind抑制文件中?
看来valgrind是对的.如果你将printf()输出解释为表明没有泄漏,那么你就不会意识到它的影响了fork().
当你分叉一个孩子时,它会获得其父母地址空间的完整副本.这通常通过写时复制页面实现,但它仍构成属于子节点的内存.在您的情况下,它包括动态分配的数组的副本arr.
子_exit()进程通过调用退出,因此虽然它继承了父进程的exit-handler注册,但是在该进程中不会调用已注册的退出处理程序.您可以这样说,因为您cleanup()只看到一次输出.因此,arrvalgrind告诉你,永远不会释放属于孩子的副本.
不过,将此称为内存泄漏有点迂腐.当程序终止时,仍然可以访问有问题的内存,此时它将被系统回收.它只是在终止之前没有明确释放.