En enquêtant ne affirmation douteuse , j'ai écrit ce petit programme de test noway.c
int proveit()
{
unsigned int n = 0;
while (1) n++;
return 0;
}
int main()
{
proveit();
return 0;
}
En testant cela, je reçois:
$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction ./a.out
Wat.
Si je compile sans optimisations, il se bloque comme prévu. J'ai regardé l'Assemblée, et sans toutes les cloches et les sifflets, la fonction main
ressemble à ceci:
_main: ## @main
pushq %rbp
movq %rsp, %rbp
ud2
Où ud2
is est apparemment une instruction spécifiquement destinée aux comportements non définis. La revendication douteuse susmentionnée, "Une fonction qui ne revient jamais est UB", est renforcée. J'ai quand même du mal à y croire. Vraiment!? Vous ne pouvez pas écrire une boucle de rotation en toute sécurité?
Je suppose donc que mes questions sont les suivantes:
Informations pertinentes
$ 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
Si vous obtenez l'ud2 pour le code qui est maintenant dans la question, alors le compilateur n'est pas un compilateur C conforme. Vous pouvez signaler un bogue du compilateur.
Notez qu'en C++ ce code serait en fait UB. Lorsque des threads ont été ajoutés (C11 et C++ 11 respectivement), une garantie de progression vers l'avant a été mise en place pour tout thread, y compris le thread d'exécution principal d'un programme qui n'est pas multithread.
En C++, tous les threads doivent éventuellement progresser, sans exception. Cependant en C, une boucle dont l'expression de contrôle est une expression constante n'est pas requise pour progresser. Je crois comprendre que C a ajouté cette exception car il était déjà courant dans le codage intégré d'utiliser une while(1) {}
pour suspendre le thread.