请以下面的示例为例。看来没有内存泄漏,但是为什么分配的总堆用法和字节不断增加呢?如果我删除第一部分(test1),valgrind结果不会显示出任何增加的堆,并且始终总堆的用法:1个Allocs,1 Frees,568字节分配
代码示例:
int main(void)
{
while(1)
{
FILE *test1;
test1 = fopen("test1", "w");
fprintf(test1, "somethingn");
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, "somethingn");
}
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)
使用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
)。
当您评论test1部分时,为什么分配不会增加?
好吧,如果您评论该部分,则删除在循环的每个运行中运行的代码部分。剩下的代码仅在子过程中运行,这意味着总的内存分配(和分配计数)在父进程中保持恒定为0。所有孩子都将进行相同的操作,从而导致相同数量的分配。
通常,标准库中使用的C代码有时需要内存来完成他们需要做的事情。文件功能需要缓冲区空间来存储字节以读取/写入,因为文件在较低级别的磁盘块读取,等等。
另外,从 fclose
的人页面:
fclose()函数通过流汇总流的流(使用fflush(3)编写任何缓冲输出数据)并关闭基础文件描述符。
在这里引用了一些缓冲数据,当您致电fclose
。