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

Mac终端终止C程序时POSIX共享内存等资源自动清理实现问题

问题根因

你的清理代码位于无限循环之后,程序正常运行时永远不会执行到该位置;同时Ctrl+C触发的SIGINT信号默认行为是直接终止进程,不会主动执行你的自定义清理逻辑。

解决方案

通过注册SIGINT信号处理函数捕捉终止信号,设置退出标志通知主循环跳出后执行清理逻辑,代码示例如下:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// 原子类型退出标志,保证信号处理函数修改变量的安全性
volatile sig_atomic_t exit_flag = 0;

// SIGINT信号处理函数,仅允许执行异步信号安全的操作
void sigint_handler(int sig) {
    exit_flag = 1;
}

int main () {
    // 注册SIGINT信号处理逻辑,sigaction比signal可移植性更强
    struct sigaction sa = {0};
    sa.sa_handler = sigint_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction注册失败");
        exit(EXIT_FAILURE);
    }

    // 原有初始化逻辑:创建共享内存、启动pthread工作线程等
    // ...

    for (;;)
    {
        // 检测到退出标志直接跳出循环
        if (exit_flag) {
            break;
        }
        // 主循环原有业务逻辑
        // ...
    }
    
    // 清理逻辑执行顺序:
    // 1. 通知所有工作线程退出,调用pthread_join回收线程资源
    // ...
    // 2. 销毁POSIX共享内存映射、释放堆内存
    destroy_shared_object(shm, MEM_MAP_SIZE);

    exit(EXIT_SUCCESS);
    return 0;
}
注意事项
  • 信号处理函数内禁止调用printf、malloc、free等非异步信号安全的函数,仅修改exit_flag这类sig_atomic_t类型的原子变量是最安全的操作
  • 如果需要覆盖更多终止场景,可以给SIGTERM、SIGQUIT等终止信号都注册同一个处理函数
  • POSIX共享内存属于内核持久化资源,进程异常崩溃时不会自动销毁,建议程序启动时先调用一次shm_unlink清除残留的共享内存对象,避免资源泄漏
  • 多线程场景下建议给所有工作线程屏蔽SIGINT信号,仅保留主线程处理信号,避免信号被随机分发到工作线程导致逻辑异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:45:02