C++ 怎么捕获Ctrl+C C++ signal处理中断信号【控制台】
技术百科
裘德小鎮的故事
发布时间:2026-01-25
浏览: 次 Ctrl+C在Windows和Linux上均触发SIGINT信号,但处理机制不同:Linux/macOS推荐sigaction(),Windows应使用SetConsoleCtrlHandler(),跨平台需统一通过轮询原子标志位实现。
Ctrl+C 在 Windows 和 Linux 上都触发 SIGINT
终端按下 Ctrl+C 时,操作系统会向当前前台进程发送 SIGINT 信号,不是 C++ 语言特性,而是 POSIX(Linux/macOS)和 Windows CRT(如 MSVC 运行时)都支持的通用机制。关键区别在于:Linux 默认终止进程,Windows 控制台默认也终止,但两者都允许你注册处理函数来拦截它。
用 signal() 注册简单处理函数,但有严重限制
signal() 是最基础的方式,适合快速响应、不涉及复杂逻辑的场景。但它在信号处理期间禁止调用大部分标准库函数(如 std::cout、malloc),且不能保证重入安全。常见错误是直接在里面打印日志或调用 std::exit() —— 这可能崩溃或死锁。
- 只允许调用异步信号安全函数(如
write()、_exit()) - 不要在 handler 中修改全局对象、调用 STL 容器方法或抛异常
- MSVC 的
signal()在 Windows 上对SIGINT支持较稳定;GCC/Clang 下推荐用sigaction()(见下条)
示例(仅用于演示,不推荐生产):
#include#include volatile std::sig_atomic_t g_stop_requested = 0; void signal_handler(int sig) { if (sig == SIGINT) { g_stop_requested = 1; // OK: sig_atomic_t 是原子读写类型 } } int main( ) { std::signal(SIGINT, signal_handler); while (!g_stop_requested) { // 做工作... } std::cout << "Exiting gracefully.\n"; }
用 sigaction() 更可靠(Linux/macOS 推荐)
sigaction() 提供更细粒度控制:可屏蔽其他信号、指定是否重启被中断的系统调用、避免信号处理函数被多次触发等。它不修改全局状态,行为可预测,是 POSIX 系统首选。
- 必须用
struct sigaction显式配置,不能像signal()那样传函数指针就完事 - 设置
sa_flags |= SA_RESTART可让阻塞式系统调用(如read())在收到信号后自动重试,而不是返回 -1 +EINTR - 用
sigfillset(&act.sa_mask)可临时屏蔽所有信号,防止嵌套中断
注意:sigaction() 在 Windows MinGW 环境可用,但原生 MSVC 不支持 —— 如果跨平台,需条件编译。
Windows 控制台专用:SetConsoleCtrlHandler()
Windows 提供了比 signal() 更底层、更可控的 API:SetConsoleCtrlHandler()。它能捕获 CTRL_C_EVENT、CTRL_BREAK_EVENT、甚至关机前的 CTRL_SHUTDOWN_EVENT,且 handler 中可以安全调用多数 Win32 API(比如 SetEvent()、PostThreadMessage())。
- handler 函数必须是
BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)类型 - 返回
TRUE表示已处理,系统不再执行默认动作(即不退出);返回FALSE则继续传递给下一个 handler 或执行默认终止 - 不能在 handler 中调用
ExitProcess()或TerminateProcess(),否则会导致未定义行为
这是 Windows 下唯一能可靠响应 Ctrl+Break 或关机通知的方式,signal() 对后者完全无效。
真正麻烦的是跨平台统一处理:SIGINT 语义在不同系统上看似一致,但底层机制、线程安全性、可调用函数集差异极大。别试图写一个“通用 handler 函数”,应该按平台分路径,在主循环里轮询 g_stop_requested 这类标志位,把信号处理降级为“设标志”,其余逻辑放在正常线程流中执行。
# ai
# 操作系统
# 的是
# 放在
# 这类
# 这是
# 能在
# windows
# 按下
# mac
# 在里面
# 不支持
# win
# word
# linux
# 循环
# 对象
# macos
# c++
# 区别
# 指针
# stream
# 线程
# signal
# 异步
# 死锁
# 信号处理
# Struct
# break
# ios
# bool
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么查看局域网电脑_Windows 11
- Win11任务栏怎么调到左边_Win11开始菜单居
- C++ STL算法库怎么用?C++常用算法函数(s
- MAC如何设置网卡MAC地址克隆_MAC终端修改物
- Python文件操作优化_大文件与流处理解析【教程
- 如何正确访问 Laravel 模型或对象的属性而非
- MAC怎么解压RAR格式文件_MAC第三方解压工具
- Mac的Time Machine怎么用_Mac系统
- Win11怎样安装网易云音乐_Win11安装网易云
- 如何在 Go 中调用动态链接库(.so)中的函数
- Win11怎么设置触控板手势_Windows11三
- Win11怎么快速锁屏_Win11一键锁屏快捷键W
- Windows10系统怎么查看设备管理器_Win1
- Mac如何将HEIC图片格式转为JPG_Mac批量
- php下载安装后memory_limit怎么设置_
- c++的位运算怎么用 与、或、异或、移位操作详解【
- Windows如何拦截2345弹窗广告_Windo
- PhpStorm怎么调试PHP代码_PhpStor
- 如何在Golang中使用内置函数_Golangle
- Windows10系统怎么查看IP地址_Win10
- PHP怎么接收前端传的时间戳_处理时间戳参数转换技
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Windows Defender扫描失败怎么办_安
- php8.4xdebug无法调试怎么办_php8.
- Win11怎么更改系统语言_Win11中文语言包下
- Python网络超时处理_健壮性设计说明【指导】
- Win10怎么限制单程序CPU占用上限_Win10
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- Win11怎么设置开机问候语_自定义Win11锁屏
- 如何使用Golang实现容器安全扫描_Golang
- C#如何使用Channel C#通道实现异步通信
- 如何在JavaScript中动态拼接PHP的bas
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- Windows怎样关闭Edge新标签页广告_Win
- 如何在Golang中使用container/hea
- 如何使用Golang进行HTTP服务性能测试_测量
- php在Linux怎么部署_LNMP环境搭建PHP
- Win10电脑怎么设置网络名称_Windows10
- C++中的协变与逆变是什么?C++函数指针与返回类
- Win11怎么卸载Photos应用_Win11卸载
- php打包exe如何加密代码_防反编译保护方法【技
- Windows10如何重置此电脑_Windows1
- Win11怎么把图标拖到任务栏_Win11固定应用
- Python异步网络编程_aiohttp说明【指导
- php485能和物联网模块通信吗_php485对接
- Win11怎么更改任务栏颜色_Windows11个
- Win11怎么退出高对比度模式_Win11取消反色
- Python函数接口稳定性_版本演进解析【指导】
- Windows10电脑怎么设置虚拟内存_Win10
- 如何在Mac上搭建Golang开发环境_使用Hom


QQ客服