在 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 提供展开数据,但不清楚该数据应包含什么或如何提供它。
在这种情况下,B 实际上不需要进行任何展开,它是否仍然必须有一个空的展开数据块,或者您可以忽略它并让异常默默地传递给 B?
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,使其不再那么琐碎,从而增强您对它的信心。