【发布时间】:2018-10-07 10:17:44
【问题描述】:
考虑以下代码sn-p:
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()
g++ 是如何解决这个问题的?由于f 的主体不可见,不应该在调用方生成代码吗?
...或者这只是一个奇怪的 Compiler Explorer 怪癖?
【问题讨论】:
-
Afaik gcc 只是使用 eh 个性函数以不同方式处理异常。 Godbolt 只是剥离它。这个discussion 似乎相关。
-
如果使用
-O3,这个问题可能会更准确,因为-Ofast无视标准合规性。 -
@DanM。确实如此,在 Godbolt 输出中也可以看到,只需打开“.text”即可。然而,目前尚不清楚 EH 人格函数如何诊断
f()的当前实例是否是从b()调用的。跳转指令执行后,堆栈上将没有证据表明它来自那里。
标签: c++ c++11 exception code-generation noexcept