0127、安全开发篇(四):异常处理
返回:C++ 泛型编程目录 · 安全开发总目录
这一章整理异常处理。C 语言通常靠返回值、错误码和宏定位问题;C++ 增加了异常机制,可以把错误沿调用链向上传播。安全开发里异常不是“偷懒不判断错误”,而是要让错误路径可控、资源能释放、日志能复盘。
6.1 C 预定义宏
C/C++ 提供一些预定义宏,适合写日志和调试信息。
| 宏 | 含义 |
|---|---|
__FILE__ |
当前文件名 |
__LINE__ |
当前行号 |
__DATE__ |
编译日期 |
__TIME__ |
编译时间 |
__FUNCTION__ |
当前函数名,常见编译器支持 |
1 |
6.3 C 错误规避
C 风格错误处理常用返回值。
1 | int read_config(const char *path) { |
复盘重点:调用者必须检查返回值,否则错误会被吞掉。
6.4 C 标准错误
C 中常见 errno、返回值、空指针判断。文件、内存、系统调用都要检查失败情况。
| 场景 | 检查 |
|---|---|
fopen |
是否返回 NULL |
malloc |
是否返回 NULL |
| 字符串转换 | 是否转换完整 |
| 文件读取 | 返回数量是否符合预期 |
6.5 C++ 抛出异常
C++ 可以用 throw 抛出异常,用 try/catch 捕获。
1 |
|
6.6 异常传播
异常会沿调用栈向上传播,直到被匹配的 catch 捕获。如果没人捕获,程序会终止。
1 | try { |
6.7 异常规范
旧式动态异常规范已经不推荐。现代 C++ 更常见的是 noexcept,表示函数承诺不抛异常。
1 | void cleanup() noexcept { |
析构函数里尤其不要抛异常。
6.8 标准异常
常见标准异常:
| 异常 | 场景 |
|---|---|
std::exception |
标准异常基类 |
std::runtime_error |
运行时错误 |
std::invalid_argument |
参数非法 |
std::out_of_range |
越界 |
std::bad_alloc |
内存申请失败 |
6.9 自定义异常
自定义异常适合表达项目自己的错误语义。
1 |
|
异常安全与资源释放
异常处理最怕资源泄漏。C++ 里优先用 RAII:资源放进对象,析构时自动释放。
1 |
|
ifstream 离开作用域会自动关闭文件。
错误处理选择表
| 方式 | 适合场景 |
|---|---|
| 返回值 | 高频、可预期、简单错误 |
errno |
C 标准库和系统调用风格 |
| 异常 | 无法在当前层处理,需要向上传播 |
| 日志 | 需要保留复盘证据 |
| RAII | 资源必须自动释放 |
安全复盘问题
| 问题 | 说明 |
|---|---|
| 是否检查失败 | 文件、内存、输入都要检查 |
| 是否泄漏资源 | 异常路径也要释放 |
| 是否吞掉异常 | 空 catch 会隐藏问题 |
| 是否泄露敏感信息 | 错误信息不要包含密码、密钥 |
| 是否有日志 | 关键错误要能复盘 |
本章最小复盘代码
1 |
|
学习检查清单
| 检查项 | 状态 |
|---|---|
| 能用预定义宏输出文件名和行号 | 待复盘 |
| 能写出返回值式错误处理 | 待复盘 |
| 能抛出并捕获标准异常 | 待复盘 |
能说明异常传播和 catch 匹配顺序 |
待复盘 |
| 能用 RAII 避免异常路径资源泄漏 | 待复盘 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ruiqy~!






