JIT编译器和异常处理

JIT compilers and exception handling

本文关键字:异常处理 编译器 JIT      更新时间:2023-10-16

在Windows x64上,假设有三个函数的调用链:

function A, written in C++
function B, generated by a JIT compiler
function C, written in C++

A调用B, B调用C,然后C抛出被A捕获的异常。B只是直线代码;它从不抛出或捕获任何异常,也不包含任何析构函数。

http://msdn.microsoft.com/en-us/library/ms235286(v=vs.80).aspx说B必须保持堆栈对齐到16字节,这是可以的。它还说必须向B提供unwind数据,但不清楚这些数据应该由什么组成,也不清楚如何提供。

在这种情况下,B 实际上必须执行任何展开,它是否仍然需要有一个空的展开数据块,或者您可以忽略它并让异常静默地传递给B?

您确实需要展开数据,正如本文所解释的:

即使你只有一个很小的函数,只调用另一个函数,你仍然需要unwind数据,或者当一个异常发生时,你的进程将被终止。

unwind数据的格式有文档记录,但它相当简洁。

Microsoft c++编译器发出与Windows SEH统一的异常处理代码。所以它是一个很好的工具,可以帮助我们了解应该如何做。从一个包含一些测试代码的虚拟项目开始:

void foo() { throw 1; }
void testNoTry() { foo(); }
void testTry() {
    try { foo(); }
    catch (int& err) {}
}

Project + Properties, C/c++, Output Files, ASM List Location =/FAcs。生成带有此代码的程序集的.cod文件。C/c++,代码生成,基本运行时检查=默认。这样可以减少噪音。构建。

用文本编辑器打开.cod文件。您将看到它将异常数据写入xdata$x段。为展开表显式命名的部分,__unwindtable$符号。很痛,不是吗?

但是在其他方面是非常好的消息:testNoTry()根本没有unwind数据。祝贺你。通过使它不那么琐碎来建立您对它的信心,例如,将foo()移动到另一个.cpp文件中并尝试/EHsa.