【问题标题】:Implicit exception handling隐式异常处理
【发布时间】:2017-01-27 22:17:05
【问题描述】:

我对 C++ 编译器如何实现异常处理有了一个基本的了解,这要归功于 Vishal Kochhar 出色的 article。基本上,只要函数中出现 try/catch 结构,编译器就会生成一个序言/尾声代码,如下所示:

push -1
push offset new_handler
mov eax, fs:[0]
push eax ; old handler saved on the stack
mov fs[0], esp
...
mov ecx, [ebp-0Ch] ; recover old handler
mov fs[0], ecx

问题是,编译器将这样的东西插入看似与异常处理无关的函数中的原因是什么?我敢肯定,根据源代码,它们的主体中没有 try/catch 块。

【问题讨论】:

  • 有时会插入隐式 try/catch 帧,因为托管类型在超出范围时需要“自动”释放。
  • C++代码和生成的汇编代码之间没有iff关系。您看到的代码模式完全有可能不是 C++ 源代码中的 try/catch 构造的指示符,无论是否隐含,它只是一种可用于支持多个更高级别构造的模式。
  • 异常必须通过抛出点和捕获点之间的调用函数,并在途中进行清理(以正确的顺序使用自动存储持续时间的析构函数清理对象等)。如果不在干预函数中做一些事情,就没有实际的方法来实现这一点。
  • 你们为什么要把答案写在 cmets 上? short question -> short answer 不代表不能正确提交答案

标签: c++ exception assembly compiler-construction x86


【解决方案1】:

这些“看似与异常处理无关”的函数可能在其局部变量上运行终结器/析构函数。对象的终结器必须在其范围结束时立即运行,无论是通过正常返回还是通过未捕获的异常,因此函数必须在序言中安装异常处理程序以确保在任何情况下都调用终结器。

在 D 中触发此行为的简单示例:

struct Foo {
    ~this() {
        ;
    };
};

int main() {
    Foo x;
    return 0;
};

也许智能编译器可以省略 nothrow 函数中的序言/尾声,例如:

struct Foo {
    ~this() nothrow {
        ;
    };
};

int main() nothrow {
    Foo x;
    return 0;
};

但似乎不是这种语言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    相关资源
    最近更新 更多