在心理上,当C ++编译将其转换为汇编程序时,我总是想知道try / throw / catch在幕后是怎么看的。但是因为我从来没有使用它,所以我从来没有去过它(有些人会说懒惰)。
用于跟踪try
s的普通堆栈,还是仅为此目的保留的单独的每线程堆栈? MSVC和g ++之间的实现是大还是小?请告诉我一些伪asm(IA-32也可以)所以我永远不必自己查看! :)
编辑:现在我了解了基于IA-32处理的MSVC实现的基础知识。任何人都知道在IA-32或其他任何CPU上使用g ++?
答案 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
指令的作用。