【发布时间】:2021-10-22 03:01:45
【问题描述】:
我正在尝试自己在不同的编译器上使用代码。 我一直在尝试查找在某些函数上禁用异常的优势(通过二进制足迹)并将其与不禁用异常的函数进行比较,实际上我偶然发现了一个奇怪的情况,最好有异常不是。
我一直在使用 Matt Godbolt 的 Compiler Explorer 进行这些检查,并且在 x86-64 clang 12.0.1 上进行了检查,没有任何标志(在 GCC 上这种奇怪的行为不存在) .
看看这个简单的代码:
auto* allocated_int()
{
return new int{};
}
int main()
{
delete allocated_int();
return 0;
}
非常直接,几乎删除了从函数allocated_int()返回的分配指针。
正如预期的那样,二进制文件的占用空间也很小:
allocated_int(): # @allocated_int()
push rbp
mov rbp, rsp
mov edi, 4
call operator new(unsigned long)
mov rcx, rax
mov rax, rcx
mov dword ptr [rcx], 0
pop rbp
ret
另外,非常直截了当。
但是,当我将 noexcept 关键字应用于 allocated_int() 函数时,二进制文件就会膨胀。我将在此处应用生成的程序集:
allocated_int(): # @allocated_int()
push rbp
mov rbp, rsp
sub rsp, 16
mov edi, 4
call operator new(unsigned long)
mov rcx, rax
mov qword ptr [rbp - 8], rcx # 8-byte Spill
jmp .LBB0_1
.LBB0_1:
mov rcx, qword ptr [rbp - 8] # 8-byte Reload
mov rax, rcx
mov dword ptr [rcx], 0
add rsp, 16
pop rbp
ret
mov rdi, rax
call __clang_call_terminate
__clang_call_terminate: # @__clang_call_terminate
push rax
call __cxa_begin_catch
call std::terminate()
clang 为什么要为我们做这个额外的代码?除了调用new(),我没有要求任何其他操作,我希望二进制文件能够反映这一点。
谢谢能解释的人!
【问题讨论】:
-
你是如何申请
noexcept的?您在使用noexcept(true)吗?此外,检查调试构建代码几乎没有意义。编译器可以/将添加它/您可以用于调试目的的代码。 -
开启优化 - 实时 - godbolt.org/z/69GTooYKz 未优化的代码有时会较大以使调试更容易,不应用作编译生成好代码还是坏代码的示例。
-
noexcept不会“禁用异常”,它会改变异常的行为——让它们调用std::terminate -
@NathanOliver 是的,我正在使用 noexcept(true) :)
-
@RichardCritten 我不想最大限度地优化优化,因为这无助于我了解编译器的自然行为。相反,我将其更改为 -O1,最小优化,它仍然比没有 noexcept 更大...
标签: c++ performance optimization clang noexcept