"Istruzioni hardware illegali" da un codice molto semplice


9

Mentre indaga su un'affermazione dubbia , ho scritto questo piccolo programma di testnoway.c

int proveit()
{
    unsigned int n = 0;
    while (1) n++;
    return 0;
}

int main()
{
    proveit();
    return 0;
}

Provando questo, ottengo:

$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction  ./a.out

Wat.

Se compilo senza ottimizzazioni, si blocca come previsto. Ho guardato l'assemblea, e senza tutte le campane e fischietti la mainfunzione è simile a questa:

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2

Dov'è ud2apparentemente è un'istruzione specifica per un comportamento indefinito. La summenzionata affermazione dubbia, "Una funzione che non ritorna mai è UB", è rafforzata. Trovo comunque difficile crederci. Veramente!? Non riesci a scrivere in modo sicuro uno spin loop?

Quindi immagino che le mie domande siano:

  1. È una lettura corretta di ciò che sta succedendo?
  2. In tal caso, qualcuno può indicarmi una risorsa ufficiale che lo verifica?
  3. Qual è una situazione in cui vorresti che si verifichi questo tipo di ottimizzazione?

Informazioni rilevanti

$ 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

3
IIRC, overflow firmato int è UB.
wildplasser,

1
^^^^ ie int n = 0===> unsigned int n = 0;o meglio ancora ..while (1);
WhozCraig,

1
Hmmm ... Il clang del compilatore Explorer ottiene un'istruzione di salto auto-target con -O gcc.godbolt.org/z/NTCQYT e una traduzione riga per riga senza di essa. Sembra coerente in molte versioni. Ma ricordo anche (anche se non cercherà) che lo standard C dice che una non terminazione è ub se è priva di effetti collaterali . Ecco Hans Boehm che spiega che ciò consente alcune ottimizzazioni del compilatore altrimenti impossibili: open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm
Gene,

1
Il comportamento indefinito è un overflow di numeri interi e non un ciclo infinito. È possibile risolvere il problema utilizzandounsigned int
MM

2
@Gene non penso che lo dica. Si può presumere che i loop senza sideffect con espressioni di controllo non const terminino ( port70.net/~nsz/c/c11/n1570.html#6.8.5p6 ) ma il loop occupato dovrebbe andare bene. L'UB è nell'overflow dei numeri interi, anche se non riesco a riprodurre l'esempio con l'istruzione UD.
PSkocik,

Risposte:


3

Se si ottiene ud2 per il codice che si trova ora nella domanda, il compilatore non è un compilatore C conforme. È possibile segnalare un bug del compilatore.

Si noti che in C ++ questo codice sarebbe effettivamente UB. Quando sono stati aggiunti thread (rispettivamente C11 e C ++ 11), è stata creata una garanzia di avanzamento in avanti per qualsiasi thread, incluso il thread di esecuzione principale di un programma che non è multi-thread.

In C ++ tutti i thread devono infine procedere, senza eccezioni. Tuttavia in C, un ciclo la cui espressione di controllo è un'espressione costante non è richiesto per progredire. La mia comprensione è che C ha aggiunto questa eccezione perché era già pratica comune nella codifica incorporata utilizzare awhile(1) {} per appendere il thread.

Domanda simile con risposte più dettagliate


Sì, ottengo il ud2codice C, ma grazie per aver incluso le informazioni sulla garanzia di avanzamento C ++ (un termine sembra che sarò in grado di ricercare) che è quello di cui mi stavo chiedendo, ma sono stato ottimizzato come Stavo preparando la domanda.
Luqui,

Una migliore formulazione di ciò che penso che il Comitato per gli Standard abbia cercato di dire è che se rinviare tutto all'interno di un ciclo oltre una determinata operazione non influirebbe in modo osservabile sul comportamento del programma, rimandando l'esecuzione del ciclo nel suo insieme tale operazione non sarebbe considerata un cambiamento di comportamento osservabile.
supercat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.