You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对比zero-cost exceptions与旧异常编译方案的汇编代码?

零开销异常与旧异常方案的汇编对比方法(Linux x64)

一、通过GCC选项直接切换异常模型

GCC支持用编译选项直接切换两种异常实现,无需更换版本:

  • 零开销异常(DWARF模型):Linux x64下GCC默认启用,也可显式指定:-fexceptions -fdwarf2-exceptions
  • 旧方案(SJLj模型):使用选项:-fexceptions -fsjlj-exceptions

具体操作步骤:

  1. 编写包含异常逻辑的测试代码,比如:
#include <stdexcept>

int test(int a) {
    if (a < 0) {
        throw std::runtime_error("negative value");
    }
    return a * 2;
}

int main() {
    try {
        test(-1);
    } catch (...) {
        return 1;
    }
    return 0;
}
  1. 分别编译生成汇编文件:
    • 零开销方案:g++ -O2 -fexceptions -fdwarf2-exceptions -S test.cpp -o dwarf.s
    • SJLj旧方案:g++ -O2 -fexceptions -fsjlj-exceptions -S test.cpp -o sjlj.s
  2. 对比两个汇编文件:零开销方案的正常执行路径无额外指令,异常处理信息存在独立的DWARF调试段;SJLj方案会在函数入口插入setjmp相关指令,正常路径有固定开销。

二、在Godbolt Compiler Explorer上快速对比

无需本地编译,直接在线对比:

  1. 选择任意支持-fsjlj-exceptions的GCC版本(如GCC 12、13)
  2. 左侧输入测试代码,右侧分栏添加两组编译选项:
    • 第一组:-O2 -fexceptions(默认启用零开销DWARF模型)
    • 第二组:-O2 -fexceptions -fsjlj-exceptions(启用旧SJLj模型)
  3. 直观对比两组汇编结果的差异。
  4. 若想使用默认旧方案的GCC版本,可选择Godbolt上的GCC 3.4.6——它在x64 Linux下默认采用SJLj异常模型,直接和新版本默认的DWARF方案对比即可。

三、核心差异总结

  • 零开销(DWARF):正常执行路径无额外指令开销,异常处理依赖编译生成的DWARF unwind信息,开销集中在异常抛出阶段。
  • SJLj旧方案:每个函数入口都会插入setjmp保存上下文,正常路径有固定开销,异常抛出时直接通过longjmp跳转至捕获点,异常触发开销相对较低。

内容的提问来源于stack exchange,提问作者svick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:35:16