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色盲模式怎么开_Win11屏幕颜色滤镜设
- c++怎么编写动态链接库dll_c++ __dec
- Python安全爬虫设计_IP代理池与验证码识别策
- Win11怎么设置默认终端应用_Windows11
- Windows蓝屏BAD_POOL_HEADER故
- 如何在Golang中实现邮件发送功能_Golang
- 企业SEO优化选择网站建设模板的技巧
- PhpStorm怎么调试PHP代码_PhpStor
- 如何在 Go 中判断变量是否为函数类型
- php8.4匿名类怎么用_php8.4匿名类创建与
- Win11怎么设置任务栏图标大小_Windows1
- Win11怎么设置系统还原_Windows11系统
- 如何在Golang中写入JSON文件_保存结构体数
- Win11怎么关闭搜索历史_Win11清除设备上的
- c++如何利用doxygen生成开发文档_c++
- 如何使用Golang encoding/json解
- c++中的CRTP是什么 c++奇异递归模板模式【
- 电脑无法识别U盘怎么办 Windows磁盘管理与驱
- Win11怎么设置快速访问主页_Windows11
- C#如何使用Channel C#通道实现异步通信
- Win11怎么关闭用户账户控制UAC_Window
- Windows如何查看和管理已安装的字体?(字体文
- c++如何获取map中所有的键_C++遍历键值对提
- c++如何使用std::bind绑定函数参数_c+
- Win11怎么更改系统语言为中文_Windows1
- PyTorch DDP 多进程训练在 Kaggle
- Windows执行文件被SmartScreen拦截
- C#如何序列化对象为XML XmlSerializ
- Win10怎样卸载DockerDesktop_Wi
- MAC如何隐藏文件夹及文件_MAC终端命令隐藏与第
- Win11玩游戏全屏闪退怎么办_Win11全屏优化
- Windows10系统怎么查看运行时间_Win10
- Windows笔记本无法进入睡眠模式怎么办?(电源
- c++ unordered_map怎么用 c++哈
- 电脑的“网络和共享中心”去哪了_Windows 1
- c++怎么设置线程优先级与cpu亲和性_c++ 多
- Windows10如何更改开机密码_Win10登录
- c++获取当前时间戳_c++ time函数使用详解
- Win11怎么设置桌面图标间距_Windows11
- Win11怎么更改任务栏颜色_Windows11个
- Go 中 defer 语句在 goroutine
- PHP主流架构怎么集成Redis缓存_配置步骤【方
- 如何解决同一段404代码在不同主机上表现不一致的问
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- Win11关机界面怎么改_Win11自定义关机画面
- Win11快速助手怎么用_Win11远程协助连接教
- Mac的“预览”如何合并多个PDF_Mac文件处理
- 如何使用Golang reflect检查方法数量_
- Windows11怎么用“记事本”自动换行与编码
- Win11怎么关闭系统推荐内容_Windows11


QQ客服