<分区>
我迷路了..我想玩一下compiler explorer尝试多线程 C 代码,并从一段简单的代码开始。代码用-O3
编译。
static int hang = 0;
void set_hang(int x) {
hang = x;
}
void wait() {
while (hang != 0) {
// wait...
}
}
令我惊讶的是,这是编译器输出:
set_hang(int):
mov dword ptr [rip + hang], edi
ret
wait():
ret
我花了一段时间才注意到我正在将代码编译为 C++ 而不是 C。切换到 C 给了我一些我期望的东西:
set_hang:
mov DWORD PTR hang[rip], edi
ret
wait:
mov eax, DWORD PTR hang[rip]
test eax, eax
je .L3
.L5:
jmp .L5
.L3:
ret
因此,当编译为 C++ 时,wait()
总是返回,无论之前将哪个值传递给 set_hang()
。我通过在我的 PC 上编译和代码确认了这一点。这段代码立即存在,而我希望它永远挂起:
int main(void) {
set_hang(1);
wait();
return 0;
}
事实上,如果我用 gcc
而不是 g++
编译它,它就会挂起。
我尝试了不同的编译器(Clang 和 GCC),这只发生在 Clang 12.0.0 或更高版本或 GCC 10.1 或更高版本上。如果我通过 --std=c++98
也会发出我期望的代码,所以它似乎是特定于 C++11 及更高版本的代码。
从 hang
中删除 static
关键字不会影响发出的程序集。
这里发生了什么?我写 C++ 已经几个月了,所以我可能缺少一些关于最新和最伟大的奇异 C++ 黑魔法的知识,但这是非常简单的代码。我一无所知。
编辑:甚至这个程序也被完全优化掉了:
// test.cpp
static int hang = 0;
static void set_hang(int x) {
hang = x;
}
static void wait() {
while (hang != 0) {
// wait...
}
}
int main(void) {
set_hang(1);
wait();
return 0;
}
编译器输出:
main:
xor eax, eax
ret
对于 Ubuntu 上的 GCC 版本 10.3.0:
此命令将挂起:g++ -O1 -o test test.cpp && ./test
而这个命令不会:g++ -O2 -o test test.cpp && ./test