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
相关产品推荐
相关产品推荐

