

新闻资讯
技术教程开启 C++ 异常(-fexceptions,GCC/Clang 默认)会让编译器为每个可能抛出或捕获异常的函数生成额外的 unwind 表(如 .eh_frame 或 .gcc_except_table),这些元数据不执行,但必须驻留在二进制中。实测表明:在嵌入式或精简场景下,仅一个空 try/catch 块就可能使目标文件增长 2–5 KiB;含多个层级调用和异常路径的模块,膨胀可达 10–30% —— 具体取决于函数数量、调用深度和 RTTI 是否启用。
-fno-exceptions 能彻底消除异常开销吗?能显著削减体积,但有前提:
__cxa_throw 等符号缺失失败std::vector::at()、std::string 构造)仍可能隐式抛异常;禁用后它们的行为变为未定义或直接 abort,需人工替换为 operator[]、reserve()+push_back() 等无异常替代方案-fno-exceptions 影响极小用工具定位真实来源:
readelf -S your_binary | grep -E '\.(eh_frame|gcc_except)'
nm -C your_binary | grep -E '__cxa|_ZSt[^\ ]*throw'
size before.elf after.elf观察
bss/data/text 变化,通常 text 增长最明显注意:.eh_frame 在 stripped 二进制中仍存在,它不属于调试信息,strip 不会删它。
try/catch 就安全了吗?不安全。即使代码里没写任何异常语法,只要链接了启用异常的标准库(如 libstdc++ 默认版本),且调用了可能抛异常的函数(std::make_unique、dynamic_cast、std::regex),编译器仍会保留 unwind 支持。真正可控的方式只有两种:
-fno-exceptions -fno-rtti,并使用 -static-
libstdc++ 配合无异常版 STL(如 libc++ 的 -DLIBCXX_ENABLE_EXCEPTIONS=OFF)-fexceptions,其余一律 -fno-exceptions,但需确保异常永不跨编译单元边界传播(否则运行时 UB)最易被忽略的是:C++17 起 noexcept 函数声明本身不减少代码体积,它只影响调用约定检查;真正起作用的是编译器开关和链接时的库选择。