I'm lost.. I wanted to play around with the compiler explorer to experiment with multithreaded C code, and started with a simple piece of code. The code is compiled with -O3
.
static int hang = 0;
void set_hang(int x) {
hang = x;
}
void wait() {
while (hang != 0) {
// wait...
}
}
To my surprise, this was the compiler output:
set_hang(int):
mov dword ptr [rip + hang], edi
ret
wait():
ret
It took me a while before I noticed that I was compiling the code as C++ instead of C. Switching to C gave me something what I would have expected:
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
Thus, when compiled as C++, wait()
always returns, no matter which value was passed before to set_hang()
. I confirmed this by compiling and the code on my PC. This code immediately exists, while I would expect it to hang foreever:
int main(void) {
set_hang(1);
wait();
return 0;
}
And indeed, if I compile this with gcc
instead of with g++
, it hangs.
I experimented with different compilers (Clang and GCC), and this only happens with Clang 12.0.0 or higer or GCC 10.1 or higher. If I pass --std=c++98
also the code I would expect is emitted, so it seems to be something specific for C++11 and higher.
Removing the static
keyword from the hang
doesn't affect the emitted assembly.
What is happening here? It has been a few months since I wrote C++, so I might be missing some knowledge about the latest and greatest exotic C++ black magic, but this is really straightforward code. I'm clueless.
Edit: Even this program is optimized away completely:
// 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;
}
Compiler output:
main:
xor eax, eax
ret
For GCC version 10.3.0 on Ubuntu:
This command will hang: g++ -O1 -o test test.cpp && ./test
And this command won't: g++ -O2 -o test test.cpp && ./test