While investigating a dubious claim, I wrote this little test program noway.c
int proveit()
{
unsigned int n = 0;
while (1) n++;
return 0;
}
int main()
{
proveit();
return 0;
}
Testing this, I get:
$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction ./a.out
Wat.
If I compile without optimizations it hangs as expected. I looked at the assembly, and without all the bells and whistles the main
function looks like this:
_main: ## @main
pushq %rbp
movq %rsp, %rbp
ud2
Where ud2
is apparently is an instruction specifically for undefined behavior. The aforementioned dubious claim, "A function that never returns is UB", is reinforced. I still find it hard to believe though. Really!? You can't safely write a spin loop?
So I guess my questions are:
Relevant info
$ clang --version
Apple clang version 11.0.0 (clang-1100.0.20.17)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
If you get the ud2 for the code that is now in the question, then the compiler is not a conforming C compiler . You could report a compiler bug.
Note that in C++ this code would actually be UB. When threads were added (C11 and C++11 respectively), there was put in place a forward progress guarantee for any thread, including the main execution thread of a program that's not multi-threaded.
In C++ all threads must eventually progress, with no exceptions. However in C, a loop whose controlling expression is a constant expression is not required to progress. My understanding is that C added this exception because it was already common practice in embedded coding to use a while(1) {}
to hang the thread.
Similar question with more detailed answers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With