2013-03-14 101 views
3

在Windows 64,假设有三个函数调用链:JIT编译器和异常处理

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则实际上做任何平仓,不是还得有一个空平仓的数据块,或者你可以忽略这一点,有默默的异常传递乙级以上?

回答

4

你需要放松数据as this article explains

即使你只是有一个小小的功能,只有调用另一个函数,你仍然需要放松身心的数据,或者在发生异常时,你的程序将简单地被终止。

format of the unwind data is documented但它是比较简洁。

+1

也相关,http://blogs.msdn.com/b/oldnewthing/archive/2012/09/10/10347674.aspx – Hasturkun 2013-03-14 11:04:21

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。