请以下面的例子为例。 似乎没有内存泄漏,但为什么总堆使用和分配的字节数不断增加? 如果我删除第一部分(test1),则valgrind结果不显示任何增加的堆并且总是显示总堆使用量:1个allocs,1个frees,568个字节分配
代码示例:
int main(void)
{
while(1)
{
FILE *test1;
test1 = fopen("test1", "w");
fprintf(test1, "something\n");
fclose(test1);
pid_t childPid;
childPid = fork();
if(childPid == 0)
{
int j;
FILE *test2;
test2 = fopen("test2", "w");
for(j = 0; j < 4; j++)
{
fprintf(test2, "something\n");
}
fclose(test2);
exit(0);
}
else
{
int returnStatus;
waitpid(childPid, &returnStatus, 0);
}
sleep(2);
}
return 0;
}
valgrind结果:
==6314== Memcheck, a memory error detector
==6314== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6314== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6314== Command: ./test
==6314== Parent PID: 6313
==6314==
==6315==
==6315== HEAP SUMMARY:
==6315== in use at exit: 0 bytes in 0 blocks
==6315== total heap usage: 2 allocs, 2 frees, 1,136 bytes allocated
==6315==
==6315== All heap blocks were freed -- no leaks are possible
==6315==
==6315== For counts of detected and suppressed errors, rerun with: -v
==6315== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==6317==
==6317== HEAP SUMMARY:
==6317== in use at exit: 0 bytes in 0 blocks
==6317== total heap usage: 3 allocs, 3 frees, 1,704 bytes allocated
==6317==
==6317== All heap blocks were freed -- no leaks are possible
==6317==
==6317== For counts of detected and suppressed errors, rerun with: -v
==6317== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==6319==
==6319== HEAP SUMMARY:
==6319== in use at exit: 0 bytes in 0 blocks
==6319== total heap usage: 4 allocs, 4 frees, 2,272 bytes allocated
==6319==
==6319== All heap blocks were freed -- no leaks are possible
==6319==
==6319== For counts of detected and suppressed errors, rerun with: -v
==6319== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
答案 0 :(得分:1)
使用描述here的massif,我们获得有关我们程序的堆使用情况的输出。我像这样使用它
valgrind --tool=massif ./a.out
然后,在massif的输出文件中(每个子进程也有一个),我们可以看到这样的行:
[...]
#-----------
snapshot=3
#-----------
time=115870
mem_heap_B=4648
mem_heap_extra_B=24
mem_stacks_B=0
heap_tree=peak
n2: 4648 (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
n1: 4096 0x4E9F380: _IO_file_doallocate (filedoalloc.c:101)
n1: 4096 0x4EAE874: _IO_doallocbuf (genops.c:398)
n1: 4096 0x4EADA46: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:828)
n1: 4096 0x4EAC11B: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1339)
n1: 4096 0x4EA0A79: fwrite (iofwrite.c:39)
n0: 4096 0x1088E5: main (in /home/.../a.out)
n1: 552 0x4E9FF2B: __fopen_internal (iofopen.c:69)
n0: 552 0x1088C4: main (in /home/.../a.out)
[...]
在这里,我们看到与文件操作相关的各种库函数(fileops.c
)为FILE
s(此处显示的fwrite
)分配内存。
好吧,如果您注释掉该部分,则删除在每次循环运行中运行的代码部分。剩下的代码仅在子进程中运行,这意味着父进程的总内存分配(和分配计数)保持为0。所有孩子都将进行相同的操作,从而产生相同数量的分配。
通常,标准库中使用的C代码有时需要内存来完成他们需要做的事情。文件功能需要缓冲区空间来存储读/写字节,因为文件在较低级别被读取为磁盘块,等等。
另外,来自fclose
的手册页:
fclose()函数刷新stream指向的流(使用fflush(3)写入任何缓冲的输出数据)并关闭底层文件描述符。
这里引用了一些缓冲数据,当你调用fclose
时也会释放这些缓冲区。