2012-12-03 8 views
13

Eventuali duplicati:
What is the point of the Noreturn attribute?Uso di _Noreturn in C11

C11 ha introdotto l'attributo _Noreturn per indicare che una funzione non ritorna.

Ad eccezione del valore di documentazione nel codice sorgente, quali altri vantaggi forniscono l'attributo e perché utilizzarlo?

+1

http://stackoverflow.com/questions/10538291/what-is-the-point-of-the-noreturn-attribute fa la stessa domanda per C++. Il ragionamento per C è esattamente lo stesso. –

+3

Il ragionamento è simile; la sintassi sembra essere totalmente diversa tra C++ ('[[noreturn]]') e C ('_Noreturn' o' noreturn' se hai incluso ''). Quindi, lo considererei un buon x-ref; Non sono sicuro dei duplicati, però. –

+2

Nomina per riaprire perché si tratta di C, e l'altro riguarda C++, due lingue completamente diverse. Anche la sintassi attuale è molto diversa. –

risposta

18

Se una funzione chiama incondizionatamente una funzione _Noreturn, il compilatore sarà in grado di capire che:

  • il codice che segue è codice morto, che consente di ottimizzare (può essere rimosso dal generato binario) e diagnostica: il compilatore sarà in grado di emettere un avviso di "codice non raggiungibile";
  • soprattutto, sapendo che il flusso normale dalla funzione viene interrotto, sarà in grado di evitare avvisi spuri su valori di ritorno mancanti, variabili non inizializzate e simili.

    Ciò è particolarmente importante con analizzatori di codice statico - il numero di falsi positivi fornite dal analizzatore statico clang in un'applicazione biggish nostro è sceso notevolmente una volta che ha segnato la nostra die funzione (log un errore fatale e terminare l'applicazione), come noreturn.

Ci può essere anche qualche altro ottimizzazione disponibili - dal momento che la funzione non ritorna mai, non c'è bisogno di spingere l'indirizzo di ritorno sullo stack, salvare lo stato dei registri e quant'altro, tutto ciò che serve è quello di passare il argomenti e fare un jmp all'inizio della funzione, senza preoccuparsi del ritorno e della pulizia post-ritorno. Ma ovviamente, dal momento che la chiamata è one-shot, la performance da spremere qui è per lo più trascurabile.

+0

da questo argomento, anche una funzione che ritorna potrebbe essere contrassegnata come _Noreturn, giusto ?? Es: 'int foo (data * arg) {++ arg-> count; barra di ritorno (arg); } '- la funzione foo potrebbe essere chiamata con un salto e quindi passare nuovamente a bar() in cui i dati vengono effettivamente restituiti. O mi sono perso il punto? – user666412

+0

@ user666412: questa è l'ottimizzazione della coda, che è per lo più non correlata.Applicare '_Noreturn' a' bar' significherebbe che * mai * ritorna; OTOH, qui il compilatore può delegare semplicemente la pulizia a 'bar' in una sola istanza specifica. Inoltre, in retrospettiva, la mia risposta pone troppa enfasi sull'aspetto dell'ottimizzazione (che è marginale per le funzioni di '_noreturn', come sono ovviamente chiamate raramente), il punto è principalmente quello di marcare il codice morto e meglio adattare gli avvertimenti nei dintorni di tali chiamate (ad es. se ho una funzione che fa 'exit (1) 'è irrilevante se fa un ritorno o meno). –

+0

Sembra ancora troppo sforzo per una chiamata che avverrà al massimo una volta in un programma. – user666412

0

Consente ulteriori ottimizzazioni da parte del compilatore. Date un'occhiata here al attributo del GCC noreturn che supporta per un po 'di tempo (la semantica è probabilmente lo stesso)

4

__attribute__((noreturn)) o _Noreturn è utile per funzioni come die():

static __attribute__((noreturn)) void die(const char *fmt, ...) { 
    /* print a formatted error message and exit */ 
    exit(EXIT_FAILURE); 
} 
/* And let's say in main() you would want to exit because of an error but unforunately GCC complains about return value. */ 
int main() 
{ 
    if (!whatever) 
     die("a nasty error message goes here\n"); 
} 

e viene utilizzato anche per le ottimizzazioni come dichiarato.

+0

[JFYI] Non è necessario "restituire" esplicitamente dalla funzione main() (sono i residui della compatibilità C) – AlexT

+0

Era solo un esempio per dimostrare cosa sarebbe successo. –