C++ try/throw/catch => machine code
在心理上,我一直在想,当C++编译成汇编程序时,如何尝试/抛出/捕捉。但是因为我从来没有用过它,所以我从来没有去检查过它(有些人会说懒惰)。
正常堆栈用于跟踪
编辑:现在我了解了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使用
请看一下这个文档,它很好地描述了异常处理的内部。