调用fork()后子进程立即出现内存泄漏的原因排查
问题
调用fork()后子进程为何会立即出现内存泄漏?据我所知,fork()后父子进程会共享内容相同的内存空间,这种情况下子进程为何会存在内存泄漏?是否需要在子进程中释放某些资源?
测试代码
#include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> int main() { int pid; pid = fork(); if (pid == 0) { int thispid = getpid(); printf("Now in child process - this pid is %d\n", thispid); system("leaks a.out"); } else { wait(NULL); printf("Now in parent process\n"); } }
终端输出
➜ -- ./a.out Now in child process - this pid is 52953 You have access to multiple processes named a.out: a) 52952 ./a.out b) 52953 ./a.out Which process? (letter or PID) b Process: a.out [52953] Path: /Volumes/VOLUME/*/a.out Load Address: 0x10e5eb000 Identifier: a.out Version: ??? Code Type: X86-64 Parent Process: a.out [52952] Date/Time: 2024-05-05 13:30:22.384 +0400 Launch Time: 2024-05-05 13:30:18.632 +0400 OS Version: Mac OS X 10.14.6 (18G103) Report Version: 7 Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks Analysis Tool Version: Xcode 11.3.1 (11C505) ---- leaks Report Version: 4.0 Process 52953: 179 nodes malloced for 27 KB Process 52953: 4 leaks for 4128 total leaked bytes. 4 (4.03K) << TOTAL >> 2 (2.02K) ROOT LEAK: 0x7fee0dd00040 [16] 1 (2.00K) 0x7fee0e800800 [2048] 2 (2.02K) ROOT LEAK: 0x7fee0dd00050 [16] 1 (2.00K) 0x7fee0e801000 [2048] Now in parent process
解答
写时复制的本质:
fork()后父子进程确实共享物理内存页,但采用**写时复制(COW)**机制——只有当某一方修改内存页时,系统才会复制该页给修改方。但内存泄漏检测的是进程用户空间中被分配但未被主动释放的内存块,和物理内存共享无关。泄漏来源是系统/库的内部分配:你看到的泄漏并非你的代码导致,而是以下几类情况:
- C标准库(如stdio缓冲区、malloc内存池)在子进程初始化或执行
system()调用时,会分配一些内部管理结构; leaks工具本身在检测过程中,会触发目标进程的额外内存分配;- 父进程继承的部分库内部内存块,子进程没有对应的释放逻辑,但这些内存对系统来说并非真泄漏。
- C标准库(如stdio缓冲区、malloc内存池)在子进程初始化或执行
这是"假泄漏":进程退出时,操作系统会自动回收该进程所有的内存、文件描述符等资源,所以这类未主动释放的内存不会造成系统级的内存泄漏。只有当子进程长期运行(比如作为守护进程)时,才需要主动管理自己分配的内存。
无需额外释放资源:对于这种短期运行的子进程,完全不需要手动释放任何资源——即使你不做任何操作,系统也会在子进程退出时清理所有资源。如果要验证这一点,可以修改子进程代码直接
exit(0),再用外部leaks命令检测,会发现这类"泄漏"消失。
内容的提问来源于stack exchange,提问作者vtav42
相关产品推荐
相关产品推荐

