2012-10-18 12 views
6

Quando lo stesso codice viene compilato con ottimizzazioni completamente disabilitate (g++ -O0) e poi di nuovo con le ottimizzazioni completamente abilitate (g++ -O3), come è possibile modificare la logica del codice sorgente stesso?In che modo le ottimizzazioni del compilatore possono influire sulla logica del codice?

Per esempio, i compilatori possono

Questi due ottimizzazioni rendono il codice eseguire più velocemente senza compromettere l'integrità del codice sorgente originale. Qualsiasi codice eseguito senza queste ottimizzazioni verrà eseguito con loro abilitato.

Tuttavia, le ottimizzazioni del compilatore possono influire anche sulla logica del codice. Ecco due esempi che conosco:

  • Removing copy constructors and assignment operators da provvisori possono rimuovere possibili effetti collaterali.
  • La risistemazione di valori aritmetici contenenti virgola mobile può influire sull'errore in virgola mobile (si spera che sia necessario l'argomento -ffast-math).

Sono stato molto sorpreso, e fortunato, a conoscere questi perché potrebbero diventare enormi potenziali trucchi nella situazione sbagliata.

Quindi voglio sapere, ci sono altri casi in cui le ottimizzazioni del compilatore C++ influenzeranno la logica del codice? Sono specificamente alla ricerca di informazioni su C++ 11 (senza alcun comportamento indefinito) sotto il compilatore g ++, ma i suggerimenti per altri compilatori sono i benvenuti.

+3

Non dimenticare di menzionare che un comportamento indefinito significherà che qualsiasi cosa vada. – Mysticial

+0

Credo che il compilatore possa anche 'non calcolare' cose che non verranno mai utilizzate in seguito. Anche se ciò non modifica la logica del tuo codice, potrebbe essere negativo se stai misurando le prestazioni. Non sono sicuro di questo però. – leo

+0

@leo Buon punto! Anche se, mi aspetto sempre che la compilazione con le ottimizzazioni si comporti più velocemente, perché è il lavoro dell'ottimizzatore. – Ryan

risposta

8

Il "come-se" Regola:

Un'implementazione è libero di ignorare qualsiasi esigenza di questo standard internazionale fino a quando il risultato è come se il requisito era stato obbedito, per quanto come può essere determinato dal comportamento osservabile del programma . Ad esempio, un'implementazione effettiva necessita non valutare una parte di espressione se può dedurre che il suo valore viene non utilizzato e che si producono effetti indesiderati a carico del comportamento osservabile del programma.

Tuttavia, lo standard menzioni un'ottimizzazione che è consentito, e che rompe il "come-se" regola:

Quando determinati criteri sono soddisfatti, un'implementazione è consentito omettere la copia/spostare costruzione di un oggetto classe, anche se la copia/spostare costruttore e/o distruttore per l'oggetto avere effetti collaterali. In tali casi, l'applicazione considera la fonte e la destinazione della/operazione copia omessa mossa come semplicemente due modi diversi di riferimento allo stesso oggetto, e la distruzione di quell'oggetto si verifica al successiva dei tempi in cui la due oggetti sarebbero stati distrutti senza l'ottimizzazione.123 Questo l'elisione delle operazioni di copia/rinomina, chiamato copia elisione, è consentito nei seguenti casi (che possono essere combinati per eliminare copie multiple):

- in una dichiarazione di ritorno in una funzione con un tipo di classe di ritorno , quando l'espressione è il nome di un oggetto automatico non volatile (diversa da una funzione parametrica o catch clausola) con lo stesso tipo cvunqualified come tipo restituito funzione, l'operazione di copia/spostamento può essere omesso da COSTRUTTRICE l'oggetto automatico direttamente nel valore di ritorno della funzione

- in un'espressione di lancio, quando l'operando è il nome di un oggetto automatico non volatile (diverso da una funzione o catch-clausola ) il cui ambito non si estende oltre la fine del blocco di prova interno che chiude (se presente), l'operazione di copia/movimento l'operando all'oggetto eccezione (15.1) può essere omesso dal creazione dell'oggetto automatico direttamente nell'oggetto eccezione

- quando un oggetto classe temporanea che dispone non è stato associato a un riferimento (12.2) sarebbe stato copiato/spostato in un oggetto di classe con lo stesso cv-tipo non qualificato, l'operazione di copia/spostamento può essere omessa da costruire l'oggetto temporaneo direttamente nella destinazione del copia omessa/spostare

- quando l'eccezione dichiarazione di un'eccezione gestore (clausola 15) dichiara un oggetto dello stesso tipo (ad eccezione cv-qualifica) come l'oggetto eccezione (15.1), l'operazione di copia/spostamento può essere omesso trattando l'eccezione dichiarazione come alias per l'oggetto eccezione se il significato del programma sarà invariati, tranne per l'esecuzione di costruttori e distruttori per l'oggetto dichiarato dalla dichiarazione di eccezione.

1

"Comportamento non specificato" è un comportamento in cui l'implementazione è libera di scegliere uno dei possibili comportamenti. In questi casi, un ottimizzatore può influire sulla scelta effettuata.

Un semplice esempio è l'ordine in cui vengono valutati gli argomenti di una funzione. Le build non ottimizzate possono utilizzare Left-to-Right o Right-to-Left, mentre le build ottimizzate possono valutare gli argomenti in un ordine "misto". Una buona ragione potrebbe essere quella di massimizzare l'opportunità di ottimizzazione della sotto-espressione comune tra gli argomenti.

Se uno qualsiasi di questi argomenti ha effetti collaterali notevoli, la logica del codice verrebbe modificata, ma se si tratta di un bug varia caso per caso.

Problemi correlati