2015-12-18 16 views
8

Ho questo frammento di codice:codice Molto strano, in determinate condizioni, tra cui le ottimizzazioni

#include <stdio.h>  

void optimization_headache()  
{  
    int t = 11;  
    int l[1047] = {0};  
    int u_lu[23] = {0};  

    int u = 0;  

    l[0] = 0;  
    l[1] = 0;  

    do {  
     u++;  
     //printf("Incrementing u, now u is %d\n", u);  
     u_lu[u + 1] = u - l[u + 1];  
    } while ((u < t * 2) && (l[u + 1] <= t));  

    printf("u = %d, l[u] = %d, t = %d, u_lu[u] = %d\n", u, l[u], t, u_lu[u]);  
}  

int main()  
{  
    optimization_headache();  

    return 0;  
} 

Su compilazione con ottimizzazioni off ($ gcc -Wall -Wextra -O0 main.c), il codice viene compilato, e ottengo il seguente output:

u = 22, l[u] = 0, t = 11, u_lu[u] = 21

Quando compilo con le ottimizzazioni complete ($ gcc -Wall -Wextra -O3 main.c), il programma si blocca e in alto indica che sta utilizzando il 100% della mia CPU. Deve essere in esecuzione per sempre nel ciclo do while.

posso ottenere il codice per compilare con ottimizzazioni pieni e funzionare correttamente cambiando una o tutte le seguenti:

1) Se io commento l[0] = 0; l[1] = 0;.

2) Se si effettua u a volatile int invece.

3) Se si decommenta il printf all'interno del ciclo do while.

Quindi, ovviamente, non capisco cosa stanno facendo le ottimizzazioni e perché cambia il comportamento del mio programma. Potrei semplicemente scegliere una delle soluzioni di cui sopra per farlo funzionare, ma voglio davvero sapere cosa sta succedendo qui. È così strano per me.

(tag Il C++ potrebbe non essere appropriato, ma vedo lo stesso comportamento con g ++ così)

+3

Il comportamento si risolve con '-fno-aggressive-loop-optimizations', il che significa che è probabile che il comportamento non definito veda [C++ compilation bug?] (Http://stackoverflow.com/q/32506643/1708801) per un dettaglio spiegazione di cosa sta facendo gcc. Molto probabilmente un accesso fuori dai limiti sta accadendo. –

+7

Il tuo codice può scrivere in 'u_lu [23]'. (fai un loop mentre 'u <22' ma 'u' viene incrementato due volte). – wimh

+0

Quale versione di gcc e quale piattaforma sei? Entrambe le versioni compilate funzionano bene sul mio Mac. –

risposta

7

Come sottolineato nei commenti, questo potrebbe accadere se si invoca undefined behavior.

Nel tuo caso, questa è la parte rilevante:

int t = 11;  
int u_lu[23] = {0};  

do {  
    u++;  
    u_lu[u + 1] = u - l[u + 1];  
} while ((u < t * 2) /*...*/);  

Il ciclo viene eseguito mentre u è più piccolo 22, in modo che possa diventare 21. Ma all'interno del ciclo, è incrementare u due volte e per iscritto al u_lu[23] . Questo è uno più poi assegnato.

Problemi correlati