在 32 位 Windows 中(至少使用 Microsoft 编译器),异常处理是使用调用堆栈上动态分配的异常帧堆栈来实现的;异常堆栈的顶部由 TIB 条目指向。运行时成本是每个需要处理异常的函数的一对PUSH
/POP
指令,将异常处理程序访问的变量溢出到堆栈上,并且在处理异常时,一个简单的链表遍历。
在64 位 Windows和Itanium / System V x86-64 ABI中,展开改为使用一个大的排序列表来描述内存中的所有函数。运行时成本是每个函数的一些表(不仅仅是涉及异常处理的表),动态生成代码的复杂性,以及在处理异常时,每个活动函数遍历函数列表一次,无论它是否与异常有关或不。
后者比前者好在哪里?我理解为什么 Itanium 模型在常见情况下比基于setjmp
/的传统 UNIX 模型便宜longjmp
,但是在 32 位 Windows 中,几个PUSH
es 和s 加上一些寄存器溢出似乎并没有那么糟糕,因为(似乎)很多POP
它提供的更快和更简单的处理。(IIRC,无论如何,Windows API 调用通常都会消耗 Ks 的堆栈空间,因此我们不会通过将这些数据强制放入表中来获得任何东西。)