`nodcept`函数中的`std :: terminate`调用,可见性有限 - gcc vs clang codegen

时间:2018-04-26 16:13:29

标签: 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不是(主干版本)

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

live example on godbolt.org

g++如何逃脱这一点?由于f的正文不可见,因此无法在调用方生成代码吗?

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

1 个答案:

答案 0 :(得分:1)

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

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

  • 如果您想在未捕获的异常上调用终止,情况已经如此
  • 如果您想要不抛出异常的安全保证,那就不提供它。

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

安德烈(Andrzej)在his article - noexcept — what for ?做一个很好的案例