2010-01-26 2 views
5

avvertimento ho notato questo comportamento interessante del compilatore g ++, se posso aggiungere una bandiera -O3 al compilatore, ottengocompilatore g ++: ottimizzazione bandiera aggiunge messaggio

otsu.cpp:220: warning: ‘x’ may be used uninitialized in this function 

Tuttavia, quando io non uso l'ottimizzazione e la usa invece un flag di debug -g Non ho ricevuto alcun avviso. Ora, mi fido del compilatore di più quando il flag -g è attivo; tuttavia, mi chiedo se questo è un comportamento ben definito che dovrebbe essere previsto?

Per chiarezza, il codice che causa questo è qualcosa lungo queste linee:

int x; //uninitialized 


getAValueForX(&x); // function makes use of x, 
        // but x is unitialized 

dove

void getAValueForX(int *x) 
{ 
    *x = 4; 
} 

o qualcosa del genere, ovviamente più complessa.

+4

inserire il codice che causa l'avviso –

+0

ok aggiornato con un esempio concreto. – ldog

+1

Con x come globale, tutto ciò che accede a x può farlo prima che venga assegnato un valore. O hai semplificato l'esempio troppo a lungo, o il tipo di analisi richiesto per dimostrare che non sarebbe al di là dell'ambito e della capacità dell'ottimizzatore. L'avvertimento è solo un effetto collaterale dell'ottimizzazione, ha l'opportunità di avvertirti in questo modo. – Clifford

risposta

15

Questo è previsto. Le ottimizzazioni causano l'esecuzione di un'analisi di codice specifica ed è così che gcc trova le variabili non inizializzate. È nella pagina di manuale:

. . . questi avvertimenti dipendono ottimizzazione

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

+1

+1 per il collegamento manuale; spiega tutto. Il che probabilmente è il motivo per cui la tua risposta è stata molto più breve della mia;) – Clifford

1

miei flag di compilazione:

CFLAGS=-W -Wall\ 
-Wno-non-template-friend\ 
-Wold-style-cast\ 
-Wsign-promo\ 
-Wstrict-null-sentinel\ 
-Woverloaded-virtual 
# -Weffc++ 

-WeffC++ può essere davvero fastidioso, così a volte ho provato, ma in generale lo tengo spento. Prova questi - e altri nel manuale - e vediamo cosa vediamo.

3

Questo è in realtà molto comune con gcc. E sì, questo è normale.

Per quanto ho capito, al fine di ottimizzare, il compilatore genera molte metriche e trasforma il codice (o, più precisamente, la rappresentazione che ha del codice) in un modo che consente il rilevamento di variabili non utilizzate per gli esempi (ci sono altri avvertimenti del genere, non ricordo la lista).

Fare la stessa cosa senza l'ottimizzazione richiederebbe di eseguire e quindi di eliminare tutta questa analisi. Questo rallenterebbe la compilazione in modo significativo senza uno scopo valido (specialmente perché, nel debug, il compilatore non suppone che riorganizzi il codice).

1

Sì, questo è un comportamento ben definito. Quando l'ottimizzatore di GCC non è abilitato, non esegue alcuni tipi di controllo del percorso di esecuzione (in modo da evitare la penalizzazione delle prestazioni nel fare questo tipo di controlli). Alcune situazioni, come l'uso di variabili non inizializzate, possono essere rilevate solo quando vengono eseguiti questi controlli aggiuntivi. Quindi, con -O0, GCC non è in grado di avvisare di queste condizioni.

1

Bene, il fatto che il compilatore possa spostare le cose intorno all'ottimizzazione può causare problemi e portare a comportamenti non definiti (come indicato negli stati del manuale di seguito); Penso che sarebbe utile vedere il codice per cercare di dare un senso.

Le scorciatoie prese dal codice ottimizzato possono occasionalmente produrre sorprendenti risultati: alcune variabili stati dichiarati potrebbero non esistere affatto; il flusso di controllo potrebbe spostarsi brevemente dove non lo si era previsto ; alcune istruzioni potrebbero non essere eseguite perché calcolano i risultati costanti oi loro valori erano già a portata di mano; alcune istruzioni possono eseguire in luoghi diversi perché erano spostati da loop.

+0

Non ha nulla a che fare con il fatto che le cose vengano spostate. Con l'ottimizzazione disattivata, il compilatore non esegue mai l'analisi che potrebbe rilevare le variabili non inizializzate. L'ottimizzazione non * causerà mai * una variabile per non essere inizializzata. –

3

L'analisi del flusso di codice eseguita dall'ottimizzatore consente di rilevare potenziali problemi che la compilazione normale (e più veloce) non è in grado di rilevare. Il problema era sempre lì, il compilatore non l'ha verificato.

Anche se questo avviso viene emesso, potrebbe non essere un problema a causa dell'effettivo utilizzo della funzione nella pratica; il compilatore supporrà che tutti i possibili valori dei tipi dei suoi argomenti (e qualsiasi variabile esterna utilizzata all'interno della funzione) possano verificarsi in tutte le combinazioni possibili - portando ad almeno un percorso in cui la variabile viene utilizzata senza che venga assegnato un valore. Il tuo utilizzo effettivo avrà un insieme molto più restrittivo di stati possibili, quindi il percorso potrebbe non verificarsi mai nella pratica. La soluzione semplice è solo per inizializzare la variabile se solo per chiudere il compilatore - non ti costerà nulla.

Uso sempre l'ottimizzatore come una forma di analisi statica di povero uomo anche quando alla fine non intendo utilizzarlo nel codice di produzione. Allo stesso modo, spesso uso più di un compilatore per lo stesso motivo. Alcuni compilatori eseguono verifiche che altri no, oppure generano messaggi con parole diverse per gli stessi errori, il che spesso aiuta nella loro interpretazione per alcuni dei messaggi più ottusi.

Citazione:

mi fido il compilatore di più quando la -g bandiera è in

Se è vero che se un compilatore ha un bug che è probabile che sia in ottimizzatore (essendo la parte più complessa), per un compilatore maturo come GCC, questa sarebbe una scoperta molto rara. Viceversa le persone spesso trovano che il loro codice di lavoro non funziona quando ottimizzato; il più delle volte il codice era sempre imperfetto (forse si basava su un comportamento definito o non definito) e l'ottimizzatore ha appena messo in luce tale difetto. Quindi ti suggerisco di trovare il tuo codice in fase di ottimizzazione, sospettare il codice prima del compilatore - si applica Rasoio di Occam.

+0

+1 Trovo che provare una varietà di compilatori possa offrire una prospettiva interessante nel tuo codice, e richiamare l'attenzione su ipotesi implicite che potresti non tenere da qualche altra parte. Questo è spesso trascurato. – asveikau

0

Ho lo stesso problema nel mio compilatore msvc 6. Inizializzando la variabile in questione, rimuove la possibilità di un percorso errato dal punto di vista del compilatore.