4

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

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

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

http://msdn.microsoft.com/en-us/library/ms235286(v=vs.80).aspx说 B 必须保持堆栈对齐到 16 个字节,这很好。它还说必须为 B 提供展开数据,但不清楚这些数据应该包含什么或如何提供它。

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

4

2 回答 2

5

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

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

展开数据的格式已记录在案,但相当简洁。

于 2013-03-14T10:44:46.770 回答
2

Microsoft C++ 编译器发出与 Windows SEH 统一的异常处理代码。所以它是一个很好的工具来看看它应该如何完成。从一个包含一些测试代码的虚拟项目开始:

void foo() { throw 1; }

void testNoTry() { foo(); }

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

项目 + 属性、C/C++、输出文件、ASM 列表位置 = /FAcs。这会生成一个 .cod 文件,其中包含此代码的程序集。C/C++、代码生成、基本运行时检查 = 默认。这减少了噪音。建造。

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

但除此之外,还有一个非常好的消息:testNoTry() 根本没有展开数据。恭喜。例如,通过将 foo() 移动到另一个 .cpp 文件并尝试 /EHsa 来增强您对它的信心。

于 2013-03-14T11:09:46.693 回答