web-dev-qa-db-fra.com

"Instruction matérielle illégale" à partir d'un code très simple

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

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:

  1. Est-ce une lecture correcte de ce qui se passe?
  2. Si oui, quelqu'un peut-il m'indiquer une ressource officielle qui le vérifie?
  3. 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
9
luqui

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.

Question similaire avec des réponses plus détaillées

3
M.M