【发布时间】:2020-03-29 16:40:33
【问题描述】:
我正在为我的一些代码检查生成的 asm,我注意到了一些 interesting stuff:
#include <mutex>
std::mutex m;
void foo()
{
m.lock();
}
生成的 asm 代码(x86-64 gcc 9.2,-std=c++11 -O2):
foo():
mov eax, OFFSET FLAT:_ZL28__gthrw___pthread_key_createPjPFvPvE
test rax, rax
je .L10 // (1) we can simply bypass lock() call?
sub rsp, 8
mov edi, OFFSET FLAT:m
call __gthrw_pthread_mutex_lock(pthread_mutex_t*)
test eax, eax
jne .L14 // (2) waste of space that will never be executed
add rsp, 8
ret
.L10:
ret
.L14:
mov edi, eax
call std::__throw_system_error(int)
m:
.zero 40
问题:
- 第 (1) 部分 -- gcc 特定:
- 它在做什么? (分配 TLS 条目?)
- 该操作失败如何让我们静默绕过
lock()呼叫?
- 第 (2) 部分——看起来每个编译器都受到了影响:
-
std::mutex::lock()can throw按标准 - ...但它永远不会使用正确的代码(如相关 SO 帖子中所述),出于所有意图和目的,
std::mutex::lock()始终是正确代码中的noexcept - 是否可以让编译器知道,以便它停止发出不必要的测试和指令块(如上面的
.L14)?
-
注意:我看不出std::mutex::lock() 的投掷比简单的abort()ing 更好。在这两种情况下,您的程序都被搞砸了(没有人期望它会失败),但至少在后一种情况下,您最终得到的 asm 代码要小得多(“只为您使用的东西付费”,记得吗?)。
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。