2016-07-18 176 views
12

Gli attributi noreturn sono necessari per le funzioni di non ritorno, oppure è solo un (probabilmente prematuro? - almeno per le uscite, non riesco a immaginare perché ottimizzare lì) l'ottimizzazione?Sono necessari gli attributi di Noreturn sulle funzioni di chiusura?

È stato spiegato che in un contesto come

void myexit(int s) _Noreturn { 
    exit(s); 
} 
// ... 
if (!p) { myexit(1); } 
f(*p); 
/// ... 

noreturn impedisce il ramo !p venga ottimizzato fuori. Ma è davvero possibile per un compilatore ottimizzare questo ramo? Mi rendo conto che la logica per l'ottimizzazione sarebbe: "Il comportamento non definito non può accadere Se p == NULL, il dereferenziamento è UB, quindi p non può mai essere NULL in questo contesto, quindi il ramo !p non si attiva". Ma il compilatore non può risolvere il problema altrettanto bene assumendo che myexit potrebbe essere una funzione che non ritorna (anche se non è esplicitamente contrassegnata come tale)?

+0

Sono riluttante a contrassegnare questo C++ anche a causa di puristi felici, ma C++ ha anche attributi noreturn ('[[noreturn]]'), e una risposta C/C++ sarebbe molto gradita. – PSkocik

+2

_ "noreturn impedisce che il ramo'! P' venga ottimizzato. "_ Perché? – mvidelgauz

+0

Possibile duplicato - http://stackoverflow.com/questions/10538291/quello-è-il-punto-di-noreturn – mvidelgauz

risposta

7

Ciò consente di eseguire diverse ottimizzazioni. Innanzitutto, per la chiamata stessa, questo può consentire una configurazione semplificata, non tutti i registri devono essere salvati, è possibile utilizzare un'istruzione jmp invece di call o simile. Quindi il codice dopo la chiamata può anche essere ottimizzato perché non vi è alcuna ramificazione al flusso normale.

Quindi sì, di solito _Noreturn è una preziosa informazione per il compilatore.

Ma come risposta diretta alla tua domanda, no, questa è una proprietà per l'ottimizzazione, quindi non è necessario.

+2

Grazie, ma questo non risponde alla domanda, però. – PSkocik

+1

@PSkocik, vedere la mia modifica. –

+1

@JensGustedt Non è molto dettagliato ma almeno risponde alla parte principale della domanda ora ;-) – PSkocik

2

Assioma: Lo standard è la risorsa definitiva su ciò che è ben definito in C.

  • La norma specifica assert, quindi utilizzando assert è ben definito.
  • assert condizionalmente chiama abort, una funzione _Noreturn, quindi è consentito.
  • Ogni utilizzo di assert è all'interno di una funzione. Pertanto le funzioni possono o non possono tornare.
  • Lo standard ha questo esempio:

    _Noreturn void g (int i) { // causes undefined behavior if i <= 0 
        if (i > 0) abort(); 
    } 
    

    Pertanto funzioni condizionalmente tornando non deve essere _Noreturn. Questo significa:

    • Per funzioni definite esternamente, il compilatore deve assumere la funzione potrebbe non ritorno e non è libero di ottimizzare la if -branch
    • Per le funzioni "internamente" definiti, il compilatore può controlla se la funzione restituisce sempre e ottimizza il ramo.

In entrambi i casi, il comportamento del programma compilato allinea con ciò un non-ottimizzazione macchina astratta C farebbe e 'as-se' si osserva regola.

+0

Il pensiero che scriveva come una prova sarebbe bello, ora guardandolo, non ne sono più sicuro. Ma risponde alla domanda che penso. :-) Sentiti libero di modificarlo per renderlo più formale. – a3f

+1

Un compilatore non può assumere che le funzioni definite esternamente "non ritornino; deve invece essere preparato per gestire entrambi i casi in cui la funzione restituisce (il codice che segue la funzione non può essere omesso) e anche i casi in cui non lo fa (il codice che segue la funzione non può influire sull'esecuzione della funzione o altro prima di cio). – supercat

+0

@supercat, riformulato. Grazie. – a3f

Problemi correlati