2014-10-28 13 views
5

Uno degli spazi dei nomi nel mio programma è distribuito tra due file. Uno fornisce il "motore", l'altro utilizza il "motore" per eseguire vari comandi. Tutte le inizializzazioni vengono eseguite sul lato "motore", inclusi i parametri di memorizzazione nella cache recuperati dalla libreria di installazione.Forza GCC a non ottimizzare una variabile non utilizzata?

Quindi, c'è engine.cpp con:

#include <stdio.h> 
    #include "ns.h" 

    namespace MyNS 
    { 

     unsigned char variable = 0; 

     void init() 
     { 
      variable = 5; 
      printf("Init: var = %d\n",variable); 
     } 

     void handler() 
     { 
      // printf("Handler: var = %d\n",variable); 
     } 
    } 

La variabile accade mai per essere riutilizzato in engine.cpp ma che sia ampiamente utilizzato in commands.cpp.

#include <stdio.h> 
    #include "ns.h" 

    namespace MyNS 
    { 
     extern unsigned char variable; 

     void command() 
     { 
      printf("Command: var = %d\n",variable); 
     } 
    } 

Dopo la compilazione e il collegamento, sto ottenendo:

Init: var = 5
Comando: var = 1

Ora, se io rimuovere il commento le printf() in handler() Ricevo:

Motore: var = 5
Comando: var = 5
Handler: var = 5

Quale sarebbe il modo "corretto" per forzare GCC non per ottimizzare la via in modo tale che l'accesso attraverso extern dell'altro file sarebbe prendi il giusto valore? Preferibilmente senza ridurre il livello -O per il resto dell'applicazione?

(per il caso di completezza, main.h e ns.h:)

#include "ns.h" 

    int main(int argc, char** argv) 
    { 
     MyNS::init(); 
     MyNS::command(); 
     MyNS::handler(); 

     return 0; 
    } 

namespace MyNS 
    { 
     void init(); 
     void command(); 
     void handler(); 
    } 

Questa testcase minimizzato non presenta questo comportamento particolare; sembra che sia necessario che questa situazione si verifichi in un ambiente molto più complesso ...

+0

Non penso che il compilatore ottimizzerebbe 'variabile' via altrimenti non penso che il programma si colleghi. – Galik

+3

Ho difficoltà a credere che un incarico a una variabile con collegamento esterno sarebbe stato ottimizzato. Sei sicuro che non sia la chiamata a 'init' che viene ottimizzata via? –

+0

Il codice stamperebbe "Init: ..." piuttosto che "Engine: ...", suppongo che si riferiscano allo stesso caso. Comunque, questo è uno strano comportamento che mi fa meravigliare in che modo le altre funzioni influenzano la 'variabile'. –

risposta

1

eh ... la soluzione era piuttosto banale.

Ho scambiato i posti della dichiarazione e la definizione della variabile.

engine.cpp:

extern unsigned char variable;

command.cpp:

unsigned char variable = 0;

In questo modo il compilatore non ha dubbi necessità per l'esistenza di questa variabile durante la compilazione commands e engine si deve raggiungere a l'istanza esistente, non può semplicemente crearne una temporanea sul posto.


EDIT: Ora ho scoperto un'altra particolarità. Il valore cambia a seconda di dove è stato scritto.La sezione del codice in questione è:

1: varso = SharedObject::Instance()->varso; 
2: memset(det_map,0,sizeof(det_map)); 
3: memset(gr_map,0xFF,sizeof(gr_map)); 
4: memset(gr_ped,false,sizeof(gr_ped)); 
5: memset(&stan,0,sizeof(stan)); 

6: stan.SOTUstage = 1; 
7: PR_SOTU = varso->NrPSOTU; 

La variabile si verifica in prossimità di un luogo in cui diversi array sono inizializzati con memset. La variabile in questione è PR_SOTU (la maiuscola viene ereditata da quando era ancora una macro e poiché agisce insieme a molte altre macro che agiscono in un contesto molto simile, è probabile che rimanga tale).

Se si sposta l'assegnazione dalla riga 7 e la si posiziona dopo le righe 1, 2 o 3, riceve il valore corretto 5. Inserito dopo la riga 4 ottiene il valore 18. Qualche cosa sotto e il valore è 1. Ho spostato la definizione della variabile in un posto diverso (era l'ultima nell'elenco di tutti i nomi globali dello spazio dei nomi, ora è la prima) a escludere la possibilità che qualcosa scriva in quella specifica posizione di memoria, ma il comportamento rimane.

+2

Il compilatore non dovrebbe essere in grado di ottimizzare comunque l'utilizzo della variabile extern. Sospetto che stia succedendo qualcos'altro. – bames53

+0

@ bames53: vedere la mia modifica. Questo comportamento è davvero particolare. –

+4

È quasi certo che ciò che stai vedendo è il risultato di un comportamento indefinito. Ottieni alcuni strumenti di analisi, analizzatori statici, valgrind, disinfettanti per indirizzi e memoria, ecc. E scopri cosa sta facendo il programma sbagliato. – bames53

Problemi correlati