0

0

C++怎么捕获Ctrl+C信号 C++ signal信号处理函数用法【系统】

穿越時空

穿越時空

发布时间:2026-01-25 11:50:02

|

993人浏览过

|

来源于php中文网

原创

Ctrl+C默认触发SIGINT,需用signal()或sigaction()注册处理函数;handler中仅能操作volatile sig_atomic_t变量,禁用非异步信号安全函数;Windows下应使用SetConsoleCtrlHandler()。

c++怎么捕获ctrl+c信号 c++ signal信号处理函数用法【系统】

Ctrl+C 默认触发 SIGINT,用 signal() 注册处理函数

按下 Ctrl+C 时,终端会向当前进程发送 SIGINT 信号。C++ 本身不提供信号机制,需调用 C 标准库signal() 函数注册处理逻辑。注意:这不是线程安全的,且仅适用于简单场景(如优雅退出)。

常见错误是把处理函数写成带参数但返回值不是 void,或忽略 signal() 的返回值检查——失败时它返回 SIG_ERR,不检查容易埋下静默失败隐患。

  • signal(SIGINT, handler) 中的 handler 必须是签名形如 void handler(int) 的函数指针
  • 注册后,首次触发 SIGINT 会调用该函数;某些系统(如 Linux)会自动重置为默认行为,需在 handler 结尾再次调用 signal(SIGINT, handler) 才能持续捕获
  • 不要在 handler 里调用 std::coutmallocnew 等非异步信号安全函数——可能引发未定义行为

用 sigaction() 替代 signal() 更可靠

signal() 行为在不同系统上不一致(比如是否自动重置、是否阻塞同类信号),POSIX 推荐用 sigaction()。它支持精确控制信号掩码、是否重启被中断的系统调用等。

关键点在于:必须显式设置 sa_handler、清空 sa_mask、指定 SA_RESTARTSA_RESETHAND 等标志位,否则可能收不到第二次信号或阻塞其他信号。

立即学习C++免费学习笔记(深入)”;

  • 声明 struct sigaction sa; 后,先用 memset(&sa, 0, sizeof(sa)) 清零,避免未初始化字段导致意外行为
  • 设置 sa.sa_handler = handler;,并调用 sigemptyset(&sa.sa_mask) 防止阻塞其他信号
  • 若希望系统调用(如 read())被中断后自动重试,加 sa.sa_flags |= SA_RESTART;若想 handler 执行完后恢复默认行为,加 SA_RESETHAND

全局 volatile 变量用于跨信号上下文通信

信号处理函数不能安全调用大多数标准库函数,所以常用一个 volatile sig_atomic_t 类型的全局变量做“标志位”,主循环定期检查它。

Lobe
Lobe

微软旗下的一个训练器学习模型的平台

下载

别用普通 intbool——编译器可能优化掉读取,或因非原子操作导致值错乱。也别在 handler 里直接修改复杂对象或调用 exit()(虽然它信号安全,但会跳过展开,RAII 资源不释放)。

  • 声明:volatile sig_atomic_t g_sigint_received = 0;
  • handler 内只做:g_sigint_received = 1;
  • 主循环中:while (!g_sigint_received) { /* do work */ },退出前做清理

Windows 下需用 SetConsoleCtrlHandler

Windows 没有 SIGINT 概念,Ctrl+C 触发的是控制台控制事件。必须用 Windows API SetConsoleCtrlHandler() 注册回调,且只对控制台程序有效。

该函数注册的 handler 运行在特殊线程上,同样禁止调用大部分 Win32 API(如 CreateThreadMessageBox),也不能执行耗时操作——系统可能强制终止进程。

  • handler 原型是 BOOL WINAPI HandlerRoutine(DWORD dwCtrlType),需判断 dwCtrlType == CTRL_C_EVENT
  • 返回 TRUE 表示已处理,系统不再调用默认处理(即不退出);返回 FALSE 则继续默认流程
  • 跨平台代码通常用 #ifdef _WIN32 分支分别处理

信号处理真正难的不是注册函数,而是确保 handler 里只做最简操作,并让主逻辑及时响应这个“中断请求”。很多崩溃都源于在 handler 中调用了看似无害的 printf 或修改了非原子变量。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

93

2023.09.25

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

73

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

283

2023.11.28

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

381

2023.08.02

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

45

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.8万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号