You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含子进程与waitpid的C程序执行leaks -atExit命令为何永久挂起?

使用leaks -atExit检测含子进程的C程序时因waitpid()导致命令无响应的原因及解决

我尝试使用leaks -atExit -- ./PROGRAM_NAME命令检测包含子进程的C程序内存泄漏。该程序单独执行时可正常退出,但当程序中包含waitpid()函数时,leaks命令无法返回。以下是复现该行为的最小代码示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main()
{
    pid_t   pid;

    pid = fork();
    if (pid == -1)
    {
        printf("Fork error\n");
        exit(EXIT_FAILURE);
    }
    if (pid == 0)
    {
        printf("Hello from the child process\n");
        exit(EXIT_SUCCESS);
    }
    printf("Hello from the parent process\n");
    if (waitpid(pid, NULL, 0) == -1)
    {
        printf("Waitpid error\n");
        exit(EXIT_FAILURE);
    }
    printf("Child process finished\n");
    return (0);
}

问题原因

  • leaks -atExit通过注入代码拦截目标进程的退出函数(如exit、_exit),在进程退出时执行泄漏检测。当程序存在父子进程时,子进程退出后leaks会优先处理子进程的检测逻辑,此时父进程的waitpid调用会阻塞等待子进程的退出状态。
  • 由于leaks的注入机制会修改子进程的退出流程,导致父进程的waitpid无法正确获取子进程的退出状态,或者leaks在处理子进程检测时占用了进程间通信的资源,最终造成父进程一直阻塞,leaks命令无法正常完成并返回结果。

解决办法

  • 手动触发泄漏检测:在父进程退出前主动调用leaks命令,避免依赖-atExit的自动拦截。例如在父进程的return 0前添加:
    #ifdef DEBUG
        char cmd[64];
        snprintf(cmd, sizeof(cmd), "leaks --list --pid=%d", getpid());
        system(cmd);
    #endif
    
    编译时加上-DDEBUG即可启用检测。
  • 改用Instruments工具:苹果官方的Instruments中的Leaks模块可以可视化追踪父子进程的内存分配与泄漏情况,不会因waitpid的阻塞逻辑导致检测卡住。
  • 调整waitpid的调用方式:使用非阻塞模式(WNOHANG参数)轮询子进程状态,确保父进程不会长时间阻塞,同时配合sleep或其他逻辑等待子进程完成:
    int status;
    while (waitpid(pid, &status, WNOHANG) == 0) {
        sleep(1);
    }
    

内容的提问来源于stack exchange,提问作者BlueJohn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:00:46