【发布时间】:2020-01-22 18:04:06
【问题描述】:
Mac OS X 10.13.4。运行此程序会触发 Valgrind 中的内存泄漏信号并泄漏系统调用:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char *ft_strcpy(char *s1, const char *s2)
{
size_t cur;
cur = -1;
while (s2[++cur] != '\0')
s1[cur] = s2[cur];
s1[cur] = '\0';
return (s1);
}
void ptr_test()
{
char *ptr;
ptr = (char *)malloc(sizeof(char) * 15);
printf("FIRST: %p\n", ptr);
ft_strcpy(ptr, "Hello, World!");
printf("SECOND: %p\n\n", ptr);
free(ptr);
}
int main(void)
{
pid_t pid;
pid = fork();
while(1)
ptr_test();
if (pid != 0)
wait(NULL);
return (0);
}
泄露系统调用:
Process: main [98746]
Path: /nfs/2018/p/patrisor/Desktop/ptr/main
Load Address: 0x1095a2000
Identifier: main
Version: ???
Code Type: X86-64
Parent Process: main [98687]
Date/Time: 2019-09-22 05:28:32.273 -0700
Launch Time: 2019-09-22 05:28:23.881 -0700
OS Version: Mac OS X 10.13.4 (17E199)
Report Version: 7
Analysis Tool: /usr/bin/leaks
Physical footprint: 280K
Physical footprint (peak): 280K
----
leaks Report Version: 3.0
Process 98746: 176 nodes malloced for 27 KB
Process 98746: 4 leaks for 4128 total leaked bytes.
Leak: 0x7f9d9ad00040 size=16 zone: DefaultMallocZone_0x1095a7000
Leak: 0x7f9d9ad00050 size=16 zone: DefaultMallocZone_0x1095a7000
Leak: 0x7f9d9b800800 size=2048 zone: DefaultMallocZone_0x1095a7000
Leak: 0x7f9d9b801000 size=2048 zone: DefaultMallocZone_0x1095a7000
瓦尔格林:
==1388== LEAK SUMMARY:
==1388== definitely lost: 32 bytes in 2 blocks
==1388== indirectly lost: 4,096 bytes in 2 blocks
==1388== possibly lost: 72 bytes in 3 blocks
==1388== still reachable: 215 bytes in 7 blocks
==1388== suppressed: 27,726 bytes in 170 blocks
==1388==
==1388== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 13 from 13)
最初我怀疑这是 free() 无法使用正确的分配地址的问题。但是,当我手动扫描进程的内存使用情况时,运行时它的使用情况并没有显着增加。后来我怀疑是子进程没有正确结束,可能是创建了僵尸进程。泄漏发生在开始的某个地方,即调用 free 的地方。是函数本身有问题,还是……?我似乎很失落。
有什么猜测吗?
【问题讨论】:
-
valgrind 应该会为您提供有关泄漏内存的分配位置的信息,这些信息将很有用。你真的打算让这两个进程进入无限循环吗?
-
如何从一个永不退出的程序中获得“泄漏摘要”?
-
将
while (1)移动到for (int i = 0; i < 1024; i++),这里没有内存泄漏。 -
在我看来,如果一个无限循环正在调用一个分配了内存的函数,然后被释放并且您碰巧终止了程序(这必须是该程序退出的方式),那么预计这个函数在释放它分配的内存之前会被中断,对吧?正如 Tokhta 所提到的,如果循环是有限的,那么该函数将释放它的内存,并且没有中间流中断导致泄漏。
标签: c memory-leaks malloc fork valgrind