0

0

如何在C++中捕获并处理异常崩溃?(健壮性设计)

冰火之心

冰火之心

发布时间:2026-03-12 19:35:31

|

411人浏览过

|

来源于php中文网

原创

C++的try/catch无法捕获段错误等底层崩溃,因其仅处理throw抛出的异常;此类问题需用信号处理(Linux)或SEH(Windows)机制,且不可恢复执行。

如何在c++中捕获并处理异常崩溃?(健壮性设计)

崩溃不是异常,try/catch 捕不到段错误和访问违规

直接说结论:C++ 的 try/catch 只能捕获用 throw 主动抛出的 C++ 异常,对 segfaultaccess violationdouble free 这类底层崩溃完全无效。这类问题发生在信号层(Unix/Linux 是 SIGSEGVSIGABRT;Windows 是结构化异常 SEH),必须用信号处理或平台特定机制介入。

常见错误现象:

  • try 块里解引用空指针,程序直接终止,catch(...) 一句不执行
  • std::thread 启动函数崩溃,主线程的 try 也救不了它
  • 第三方库内部触发 abort()catch 无感知

实操建议:

腾讯交互翻译
腾讯交互翻译

腾讯AI Lab发布的一款AI辅助翻译产品

下载
  • Linux/macOS 下用 signal(SIGSEGV, handler) 注册信号处理器,但注意:信号处理函数内只能调用异步信号安全函数(write_exit 可用,printfmalloc 不可用)
  • Windows 下用 SetUnhandledExceptionFilter 捕获 SEH,再用 MiniDumpWriteDump 写崩溃转储
  • 不要在信号/SEH 处理器里尝试“恢复执行”——栈已损坏,继续跑大概率二次崩溃

什么时候该用 std::set_terminate

当未捕获的 C++ 异常穿透到 main 函数外时,会调用 std::terminate。默认行为是调用 std::abort,导致进程退出且无堆栈信息。这不是崩溃捕获,而是异常兜底出口。

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

使用场景:

  • 确保所有未处理异常至少留下日志(比如记录异常类型和当前线程 ID)
  • 配合调试器,在开发环境触发断点(__debugbreak()raise(SIGTRAP)

实操建议:

  • std::set_terminate 设置自定义终止函数,但函数内禁止抛出新异常(否则直接调用 std::abort
  • 避免在其中做复杂操作:不能用 std::cout(可能已被析构)、不能分配内存、不能锁 mutex(死锁风险)
  • 示例精简写法:
    void my_terminate() {
        write(STDERR_FILENO, "Uncaught C++ exception\n", 23);
        _exit(1);
    }
    std::set_terminate(my_terminate);

std::unexpected 已被弃用,别碰它

C++11 起,动态异常规范(如 void foo() throw(std::runtime_error))已被废弃,std::unexpected 和相关机制彻底失效。现代编译器(GCC/Clang/MSVC)遇到带 throw(...) 声明的函数抛出声明外异常时,直接调用 std::terminate,跳过 std::unexpected

为什么容易踩坑:

  • 老项目代码或过时教程还在用 throw(),误以为能靠 std::set_unexpected 拦截
  • 启用 -Wdeprecated 编译选项也未必报错,尤其在 C++14 模式下兼容旧语法

实操建议:

  • 一律改用 noexcept 替代 throw()noexcept(false) 等价于不写
  • 如果真需要运行时检查异常类型,自己封装 try/catch + 类型判断,别依赖语言级机制

健壮性设计真正要做的三件事

指望一套“万能崩溃捕获”机制是错的。生产环境健壮性靠的是分层防御,而不是某个神奇函数。

关键动作:

  • 用 AddressSanitizer(-fsanitize=address)和 UndefinedBehaviorSanitizer 在开发/测试阶段暴露内存错误,比线上捕获崩溃更有价值
  • 对关键路径做输入校验(比如指针非空、容器索引在 [0, size()) 内),把崩溃前移到可诊断的 assertthrow
  • 进程级隔离:高风险模块(如解析第三方二进制格式)放进独立子进程,主进程用 waitpid 监控其退出状态,崩溃不影响主流程

最容易被忽略的一点:信号处理函数里无法安全调用 backtrace()abi::__cxa_demangle —— 它们依赖 malloc 和符号表,而崩溃时刻这些设施本身可能已不可用。真要堆栈,得用 libunwind 配合预先映射的只读符号缓存,或者直接依赖 gdb --batch 离线分析 core dump。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
printf用法大全
printf用法大全

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

76

2023.06.20

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

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

306

2023.11.28

c++怎么把double转成int
c++怎么把double转成int

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

334

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

106

2025.10.23

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

186

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

134

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

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

精品课程

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

共94课时 | 11.2万人学习

C 教程
C 教程

共75课时 | 5.4万人学习

C++教程
C++教程

共115课时 | 21.6万人学习

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

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