c++ - 在可见性有限的 `std::terminate` 函数中调用 `noexcept` - gcc vs clang codegen

标签 c++ c++11 exception code-generation noexcept

考虑以下代码片段:

void f();

void a()          { f(); }
void b() noexcept { f(); }

在上面的场景中,f 的主体对于当前翻译单元中的编译器是不可见的。因此,由于 b 被标记为 noexcept,必须在调用方生成额外的代码以确保异常被捕获并且 std::terminate 被调用。

这就是 clang++ -Ofast -std=c++2a 所做的(主干版本):

a(): # @a()
  jmp f() # TAILCALL
b(): # @b()
  push rax
  call f()
  pop rax
  ret
  mov rdi, rax
  call __clang_call_terminate
__clang_call_terminate: # @__clang_call_terminate
  push rax
  call __cxa_begin_catch
  call std::terminate()

但是,g++ -Ofast -std=c++2a 不会(trunk 版本):

a():
  jmp f()
b():
  jmp f()

live example on godbolt.org


g++ 是如何解决这个问题的?由于 f 的主体不可见,难道不应该在调用方生成代码吗?

...或者这只是一个奇怪的 Compiler Explorer 怪癖?

最佳答案

正如@ach 回答的那样,有一个 bug opened on gcc bug tracker .但如果我可以这么说,这不是一个主要问题。

影响是异常会泄漏而不是终止程序但是:

  • 如果你想在未捕获的异常上调用终止,那已经是这样了
  • 如果您想要不抛出异常的安全保证,那么它不会提供。

我能想到的唯一情况是在开发过程中。或者在环境中,如果契约(Contract)被破坏(当生命受到威胁时)必须失败;在这种情况下,编译器和要使用的功能受到严格控制。

Andrzej 在 his article - noexcept — what for ? 中表现出色

关于c++ - 在可见性有限的 `std::terminate` 函数中调用 `noexcept` - gcc vs clang codegen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50047658/

相关文章:

c++ - 如果输入大小已知,std::unordered_map 如何优化批量插入

java - 对未知类型的数组列表进行排序,如果对象不可比较则抛出异常

java - 接口(interface)和异常

C++——继承

c++ - 如何使用 cmake 在我的代码中包含一个库?

c++ - gdb: 在 0x2aaaaaaab000 添加的符号文件系统提供的 DSO 中找不到可加载的部分

c++ - 模棱两可的模板怪异

arrays - 有没有办法强制对std::array进行完全初始化

c++ - C++ 中类似 Python 的 map

objective-c - 当我将对象替换或插入到 nsmutable 数组中时,出现异常