关于程序集:C ++ try / throw / catch =>

C++ try/throw/catch => machine code

在心理上,我一直在想,当C++编译成汇编程序时,如何尝试/抛出/捕捉。但是因为我从来没有用过它,所以我从来没有去检查过它(有些人会说懒惰)。

正常堆栈用于跟踪trys吗,还是单独保留每个线程的堆栈用于此目的?MSVC和G++之间的实现是大是小?请给我看一些伪ASM(IA-32也可以),这样我就不用亲自检查了!:)

编辑:现在我了解了MSVC在IA-32处理上的实现基础。有人知道IA-32上的G++或者其他CPU吗?


异常处理程序的不良实现会在输入try子句时为运行时堆栈上的每个try子句推送某种异常处理程序块,并在退出try子句时将其弹出。保存最近一次推送异常处理程序块地址的位置也会得到维护。通常,这些异常处理程序被链接在一起,以便通过从最新版本到旧版本的链接找到它们。当发生异常时,会找到指向上一次推送的eh处理程序块的指针,并检查该"try"子句的eh cases的处理。对eh实例的命中会导致堆栈清理回到推送eh的位置,并将控制权转移到eh实例。没有对eh的点击会导致找到下一个eh,并且过程会重复。Windows 32位SEH方案就是这个版本。

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

好的实现只需记录出现try子句的范围表。这意味着进入/退出try子句的开销为零。(我的Parlanse Parallel编程语言使用这种技术)。异常查找表中异常点的PC,并将控制权传递给表选择的EH。eh代码根据需要重置堆栈。又快又漂亮。我觉得Windows64位的eh是这种类型,但我没有仔细看。


这是一篇关于这个主题的非常有价值的文章:C++编译器如何实现异常处理


早在1997年,微软杂志的"引擎盖下"系列就对这个主题进行了深入的研究:

关于Win32深度的速成课程?结构化异常处理


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


Asm从GooBoogle编译器资源管理器,对于X8664系统V调用约定与G+ 8.2的C++ ABI,用于捕获的函数和抛出的函数。

x86-64 SystemV使用.eh_frame部分作为堆栈展开元数据,因此异常助手库函数知道如何遍历堆栈和恢复寄存器。这就是.cfi指令所做的。


请看一下这个文档,它很好地描述了异常处理的内部。