C ++ try / throw / catch =>机器代码

时间:2009-08-25 21:48:52

标签: c++ assembly exception-handling try-catch

在心理上,当C ++编译将其转换为汇编程序时,我总是想知道try / throw / catch在幕后是怎么看的。但是因为我从来没有使用它,所以我从来没有去过它(有些人会说懒惰)。

用于跟踪try s的普通堆栈,还是仅为此目的保留的单独的每线程堆栈? MSVC和g ++之间的实现是大还是小?请告诉我一些伪asm(IA-32也可以)所以我永远不必自己查看! :)

编辑:现在我了解了基于IA-32处理的MSVC实现的基础知识。任何人都知道在IA-32或其他任何CPU上使用g ++?

6 个答案:

答案 0 :(得分:20)

异常处理程序的不良实现在输入try子句时为运行时堆栈上的每个try子句推送某种异常处理程序块,并在退出try子句时将其弹出。还保持保存最近推送的异常处理程序块的地址的位置。通常,这些异常处理程序链接在一起,因此可以通过以下从最新版本到旧版本的链接找到它们。当发生异常时,找到指向最后推送的EH处理程序块的指针,并检查该“try”子句的EH情况的处理。对EH情况的命中导致堆栈清理发生回到推送的EH点,并且控制转移到EH情况。 EH上没有命中导致找到下一个EH,并且该过程重复进行。 Windows 32位SEH方案就是这个版本的一个版本。

这是一个糟糕的实现,因为程序为每个try子句支付运行时价格(push then pop),即使没有发生异常也是如此。

良好的实现只是记录一个范围表,其中出现try子句。这意味着进入/退出try子句的开销为零。 (我的PARLANSE parallell编程语言使用这种技术)。查找表中异常点的PC的异常,并将控制权传递给表所选的EH。 EH代码根据需要重置堆栈。快而美。 我认为Windows 64位EH属于这种类型,但我没有仔细看过。

答案 1 :(得分:15)

这是一篇关于这个主题的非常有价值的文章: How a C++ compiler implements exception handling

答案 2 :(得分:8)

微软期刊的“Under the Hood”系列在1997年对这个主题进行了深入研究:

A Crash Course on the Depths of Win32™ Structured Exception Handling

答案 3 :(得分:4)

C ++标准委员会发布了一篇关于“C ++性能”的技术报告,以揭穿关于C ++功能如何减慢你的速度的许多神话。这还包括有关如何实现异常处理的详细信息。本技术报告的draft免费提供。检查5.4.1节。 “异常处理实施问题和技术”。

答案 4 :(得分:0)

查看this document,它很好地描述了异常处理的内部结构。

答案 5 :(得分:0)

来自the Godbolt compiler explorer 的Asm,用于带有g ++ 8.2的C ++ ABI的x86-64 System V调用约定,用于捕获和抛出的函数。

x86-64系统V将.eh_frame部分用于堆栈展开元数据,因此异常帮助程序库函数知道如何遍历堆栈并还原寄存器。这就是.cfi指令的作用。