fork()子进程内存泄漏原因?Mac OSX 10.13.3 leaks检测问题问询
关于fork()子进程内存泄漏与Mac OSX检测结果的解析
咱们先拆解第一个问题,再聚焦你这段代码的具体场景。
问题1:fork()创建的子进程出现内存泄漏的常见原因
- 僵尸进程未回收:如果父进程没调用
wait()/waitpid()这类函数,子进程退出后会变成僵尸进程,占用进程表项和少量内存资源,这种情况经常会被内存检测工具误判为内存泄漏。 - 子进程自身内存未释放:如果子进程运行时用
malloc()、new等分配了内存,但没在退出前释放,且子进程要么长期运行,要么异常崩溃没触发清理逻辑,就会造成真正的内存泄漏。 - 系统资源未关闭:子进程打开的文件描述符、套接字、共享内存等资源,如果没主动关闭,这些资源占用的内存/系统条目也会被工具统计为“泄漏”。
- 检测工具的误判:有些内存检测工具对fork的场景处理不够精细,会把父进程复制给子进程的内存区域,或者子进程初始化时分配的长期使用内存,误标记为泄漏——尤其是当子进程一直运行不退出时。
问题2:Mac OSX 10.13.3下System Leaks检测到4处泄漏的原因
先看你提供的代码:
#include <sys/wait.h> #include <stdio.h> #include <unistd.h> int main(void) { int st; if (fork()) wait(&st); else while (1); }
这段代码里,父进程fork后调用wait()等待子进程,但子进程进入了死循环一直运行,根本不会退出。System Leaks检测到的“泄漏”,本质是Mac OSX系统和C运行时为子进程初始化分配的资源,因为子进程持续运行没有释放,被工具判定为泄漏,具体拆解:
- 两个2048字节的泄漏:这大概率是Mac OSX的C运行时(比如libSystem库)为子进程初始化的标准IO缓冲区——stdin、stdout、stderr默认的缓冲区大小通常是2048字节,子进程一直运行,这些缓冲区会被持续占用,工具就标记为泄漏。另外也可能是存储进程环境变量、命令行参数的缓冲区。
- 两个16字节的泄漏:这应该是系统为子进程创建的小型内部管理结构,比如线程控制块(TCB)的部分内存,或者libc初始化时分配的小型元数据结构。同样,因为子进程不退出,这些资源一直被占用,被工具识别为泄漏。
需要说明的是:这里的“泄漏”其实是持续性资源占用,不是传统意义上的“内存泄漏”(即分配后无法访问且未释放)。只要子进程退出,父进程的wait()会触发系统回收所有子进程的资源,这些“泄漏”标记就会消失。而你看到的4处特定大小的泄漏,是Mac OSX 10.13.3这个特定版本的系统和libc实现的特性导致的。
内容的提问来源于stack exchange,提问作者ahrytsen




