En enquêtant sur une affirmation douteuse , j'ai écrit ce petit programme de testnoway.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'assemblage, et sans toutes les cloches et les sifflets, la main
fonction ressemble à ceci:
_main: ## @main
pushq %rbp
movq %rsp, %rbp
ud2
Où ud2
est apparemment se trouve une instruction spécifique pour un comportement non défini. 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:
- Est-ce une lecture correcte de ce qui se passe?
- Si oui, quelqu'un peut-il m'indiquer une ressource officielle qui le vérifie?
- Dans quelle situation souhaiteriez-vous que ce type d'optimisation se produise?
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
int n = 0
===>unsigned int n = 0;
ou mieux encore ..while (1);
unsigned int
Réponses:
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 multi-thread.
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 un
while(1) {}
pour suspendre le thread.Question similaire avec des réponses plus détaillées
la source
ud2
code C, mais merci d'avoir inclus les informations sur la garantie de progression de C ++ (terme qu'il semble que je pourrai rechercher), c'est ce que je demandais vraiment, mais j'ai été optimisé comme Je préparais la question.