获取当前GCC异常模型

11

g++使用DWARF2sjljseh异常模型构建。 MinGW-builds提供了不同异常模型的g++版本。 我想从gcc工具链中确定正在使用哪种异常模型。是否有一个g++参数可以输出编译器的默认异常模型?


2
看起来你可以通过检查汇编编译的输出,查找“_Unwind_SjLj_Resume”或“_Unwind_Resume”来确定gcc是否使用sjlj,因为这是用于libstdc ++配置脚本所做的。 - Matt Clarkson
1
你也可以在 gcc -v 的输出中检查 --enable-sjlj-exceptions - Matt Clarkson
3个回答

15

编辑:最初,我正在测试在g++ -v中描述的配置标志。正如Jonathon Wakely在评论中指出的那样,这是不好的做法

一种检查方法是编译为汇编代码:

struct S { ~S(); };
void bar();
void foo() {
  S s;
  bar();
}

g++ -S <filename> -o output.s的结果中包含以下异常引用:

MinGW-4.8.1-x86-posix-sjlj:

.def    ___gxx_personality_sj0; .scl    2;  .type   32; .endef
.def    __Unwind_SjLj_Register; .scl    2;  .type   32; .endef
.def    __Unwind_SjLj_Unregister;   .scl    2;  .type   32; .endef
.def    __Unwind_SjLj_Resume;   .scl    2;  .type   32; .endef

MinGW-4.8.1-x86-posix-dwarf:

.def    ___gxx_personality_v0;  .scl    2;  .type   32; .endef
.def    __Unwind_Resume;    .scl    2;  .type   32; .endef

MinGW-4.8.1-x64-win32-sjlj:

.def    __gxx_personality_sj0;  .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Register;  .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Unregister;    .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Resume;    .scl    2;  .type   32; .endef

MinGW-4.8.1-x64-posix-seh:

.def    __gxx_personality_seh0; .scl    2;  .type   32; .endef
.def    _Unwind_Resume; .scl    2;  .type   32; .endef

MinGW-4.8.1-x64-posix-sjlj:

.def    __gxx_personality_sj0;  .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Register;  .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Unregister;    .scl    2;  .type   32; .endef
.def    _Unwind_SjLj_Resume;    .scl    2;  .type   32; .endef

FC17-g++-4.7.2-x64:

.cfi_personality 0x3,__gxx_personality_v0
.globl  __gxx_personality_v0
call    _Unwind_Resume

看起来我们应该搜索 __gxx_personality_([a-z])(0-9]+),然后将第一个捕获组与以下内容进行比较:

  • v = dwarf
  • seh = seh
  • sj = sjlj

1
这是不正确的,因为文档中说,默认值(即当您不使用任何--enable--disable选项时使用的值)取决于平台。 - Jonathan Wakely
谢谢,乔纳森。仍在研究通过编译代码来解决异常模型的问题。 - Matt Clarkson
2
@JonathanWakely,我更新了答案,去掉了配置标志检查,感谢你的帮助。我添加了一些编译异常处理片段的示例,这些示例在stdlibc++配置脚本中找到,然后查看汇编代码以确定正确的基本人格。我使用以下内容作为参考:http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf - Matt Clarkson

4

补充以上答案,GCC有一个预定义宏可以在编译时识别是否使用SJLJ异常模型:

__USING_SJLJ_EXCEPTIONS__

如果编译器使用基于setjmp和longjmp的旧机制处理异常,则定义此宏,值为1。

参见https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

根据文档,自至少3.1.1版本以来就可用;我刚在MinGW-w64下的GCC 7.1上测试了它。


0

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

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