sjlj、dwarf和seh之间有什么区别?

179

我找不到足够的信息来决定使用哪个编译器来编译我的项目。在不同计算机上模拟过程的几个程序中,在 Linux 上,我使用 GCC,一切都很好。我可以优化代码,编译速度快,并且内存占用不多。

我使用 MSVC 和 GCC 编译器进行自己的基准测试。后者为每个子体系结构生成稍微更快的二进制文件。尽管编译时间比 MSVC 长得多。

因此,我决定使用 MinGW。但是找不到有关 MinGW 中异常处理方法及其实现的任何说明。我可以使用不同的发行版适用于不同的操作系统和架构。

考虑因素:

  • 对我来说,编译时间和内存不重要,唯一重要的是运行时优化。我需要我的程序足够快,慢的编译器可以接受。
  • 操作系统:Microsoft Windows XP / 7 / 8 / Linux
  • 架构:Intel Core i7 / Core2 / 和一个非常旧的运行 XP 的 i686 :P

8
我很惊讶gcc能够产生比MSVC更快的代码;在过去的几年里一定有所改变... - trojanfoe
22
我被告知很多次要使用MSVC而不是MinGW。每个人都认为MSVC更快!我测试了MinGW 7.2和MSVC 2010,使用一个简单的CPU爆炸程序。在corei7上使用“-O3 -mtune = corei7”,GCC比MSVC快45%。 - sorush-r
7
根据我的经验,使用一个国际象棋走法生成器(其中使用了位板技术),微软视窗编译器(MSVC)和英特尔 C++ 编译器比 GNU 编译器(gcc)快10%,但那是两年前的情况... - trojanfoe
3
在那个时候,45%更快意味着我需要执行的时间少了45%。如果我没记错的话,我们的分子几何建模软件在特定测试中的执行时间为134秒(gcc)和194秒(msvc)。然而现在我认为我的测量方法是不正确和不足的(: - sorush-r
3
@sorush-r 我明白了,你计算了(194-134)/134,结果接近于45%,谢谢。 - Wolf
显示剩余2条评论
2个回答

126

MinGW-w64 Wiki上有一个简短的概述:

为什么mingw-w64 gcc不支持Dwarf-2异常处理?

Windows上的Dwarf-2 EH实现根本没有设计用于在64位Windows应用程序下工作。在win32模式下,异常展开处理程序无法通过非DW2感知代码进行传播,这意味着通过任何非DW2感知的“外部框架”代码传递的任何异常都将失败,包括Windows系统DLL和使用Visual Studio构建的DLL。 GCC中的Dwarf-2展开代码检查x86展开汇编,并且在没有其他Dwarf-2展开信息的情况下无法继续执行。

对于win32和win64,SetJump LongJump异常处理方法在大多数情况下都有效,但不适用于一般保护故障。正在开发gcc中的结构化异常处理支持,以克服dw2和sjlj的弱点。在win64上,展开信息放置在xdata-section中,而不是堆栈上的.pdata(函数描述符表)。对于win32,处理程序链位于堆栈上,并需要由真正执行的代码保存/恢复。

GCC GNU关于异常处理:

GCC支持两种异常处理(EH)方法:

  • DWARF-2(DW2)EH,需要使用DWARF-2(或DWARF-3)调试信息。 DW-2 EH可能会导致可执行文件略微膨胀,因为必须在可执行文件中包含大型调用堆栈展开表。
  • 基于setjmp/longjmp(SJLJ)的一种方法。 SJLJ-based EH 比 DW2 EH 慢得多(即使在没有抛出异常时也会惩罚正常执行),但可以跨越未使用GCC编译或没有调用堆栈展开信息的代码工作。

[...]

结构化异常处理(SEH)

Windows 使用其自己的异常处理机制,称为结构化异常处理(SEH)。 [...] 不幸的是,GCC尚不支持SEH。 [...]

另请参阅:


7
谢谢提供链接。我将在32位系统上使用DW2,在64位系统上使用SEH。mingwbuilds(4.8)中有SEH可用。我应该等待4.8的稳定版本还是可以使用目前的版本?它已经成功编译了。我正在使用带有SEH的4.8制作我的项目依赖项,目前还没有出现问题... - sorush-r
2
所有依赖项(包括Boost库、OpenSSL、ICU、freeGLUT)都已编译,但Qt最终出现了许多内部编译器错误。我想我会等待4.8稳定版本的发布。 - sorush-r
你使用了Qt的二进制文件还是自己编译的? - user2127352
4
@woreos 我使用自己构建的Qt程序。我发现既不是Qt也不是GCC 4.8的问题,而是我的内存有问题。[1] (http://superuser.com/questions/575482/install-windows-8-for-second-time-failed)现在一切都正常运行。 - sorush-r

97
SJLJ(setjmp/longjmp):-适用于32位和64位-不是“零成本”:即使没有抛出异常,它也会产生轻微的性能损失(在异常重代码中约为15%)-允许异常遍历例如Windows回调
DWARF(DW2,dwarf-2)-仅适用于32位-没有永久运行时开销-需要整个调用堆栈启用dwarf,这意味着无法通过例如Windows系统DLL抛出异常。
SEH(零开销异常)-将在64位GCC 4.8中提供。
来源:https://wiki.qt.io/MinGW-64-bit

2
抱歉,源链接已添加。 - user2127352
22
所以现在在2016年,我们可以解决这个问题并且始终使用SEH。 - rustyx
9
只有当你的目标是 x86_64 时,才能这样做。 - sohnryang
2
那么x86的Dwarf呢? - bsguru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接