2009-08-04 8 views
18

Uso l'inizializzazione statica per semplificare il processo di registrazione di alcune classi con una factory in C++. Sfortunatamente, penso che il compilatore stia ottimizzando gli oggetti "inutilizzati" che sono pensati per fare il lavoro utile nei loro costruttori. C'è un modo per dire al compilatore di non ottimizzare una variabile globale?Come impedire la compilazione delle variabili globali "non utilizzate"?

class SomeClass { 
    public: 
     SomeClass() { 
      /* do something useful */ 
     } 
}; 

SomeClass instance; 

Il mio punto di interruzione nel costruttore di SomeClass non viene colpito. Nel mio codice attuale, SomeClass si trova in un file di intestazione e l'istanza si trova in un file di origine, più o meno solo.

EDIT: Come indovinato da KJAWolf, questo codice è in realtà compilato in una lib statica, non nell'eseguibile. Il suo scopo è quello di registrare alcuni tipi forniti anche dal lib statico con una lista statica di tipi e i loro creatori, per una fabbrica da leggere in costruzione. Poiché questi tipi sono forniti con la lib, non è desiderabile aggiungere questo codice all'eseguibile.

Inoltre, ho scoperto che spostando il codice su un altro file sorgente che contiene un altro codice esistente, funziona correttamente. Sembra che avere un file composto esclusivamente da questi oggetti globali sia ciò che sta causando il problema. È come se quell'unità di traduzione fosse completamente ignorata.

+1

Il file sorgente è parte dell'eseguibile o fa parte di una libreria statica? – KJAWolf

+0

Aha, buon lavoro di divinazione. In realtà il file sorgente fa parte di una lib statica. Ciò causerebbe un problema? Sono sicuro all'80% di aver fatto la stessa identica cosa prima e che ha funzionato. –

+0

Ho avuto lo stesso problema: http://stackoverflow.com/questions/599035/force-visual-studio-to-link-all-symbols-in-a-lib-file – Lodle

risposta

34

Il compilatore non è autorizzato ad ottimizzare gli oggetti globali.
Anche se non vengono mai utilizzati.

Un altro elemento sta accadendo nel tuo codice.
Ora, se hai costruito una libreria statica con il tuo oggetto globale e quell'oggetto globale non è referenziato dall'eseguibile, non verrà inserito nel file eseguibile dal linker.

+9

l'ho svalutato perché penso che sia l'unica risposta che inchioda il vero problema; Come dice l'intervistatore "Sembra che avere un file composto esclusivamente da questi oggetti globali sia ciò che sta causando il problema, è come se quell'unità di traduzione fosse completamente ignorata". L'unità di traduzione viene ignorata nel senso che viene omessa dal linker perché si trova in una libreria. Se un oggetto si trova in una libreria e non viene chiamato da nessuna parte nell'app, viene omesso, è l'intera idea delle librerie! –

+0

Idem, che ha colpito l'unghia sulla testa. Ho risvegliato anche la risposta di Pavel visto che anche lui ha capito bene :) –

+1

Quindi come lo risolviamo? – Sam

5

Il compilatore non dovrebbe mai ottimizzare tali globalmente - se lo fa, è semplicemente rotto.

+3

Se il compilatore non può rilevare l'uso del globale, può ometterlo. GCC (G ++ in questo contesto) può e deve omettere alcune variabili - ad esempio, le vecchie trucchetti con la "incorporare una versione nel file oggetto" non funzionano con il GCC moderno - il valore statico del file viene rilevato come non utilizzato e ottimizzato dall'oggetto file. –

+0

file static! = Global –

+0

Se hanno un cnstructor, esiste un potenziale effetto collaterale dall'uso del costruttore. Poiché gcc non esegue l'analisi di funzioni incrociate, non sarebbe mai in grado di rilevare il potenziale di un effetto collaterale e quindi non sarebbe consentito rimuoverlo. –

2

Per costruire Arthur Ulfeldt, volatile dice al compilatore che questa variabile può cambiare al di fuori della conoscenza del compilatore. L'ho usato per mettere una dichiarazione per consentire al debugger di impostare un punto di interruzione. È anche utile per i registri hardware che possono cambiare in base all'ambiente o che richiedono una sequenza speciale. Ad esempio, la porta seriale riceve il registro e alcuni registri del cane da guardia.

+1

No, dice semplicemente il compilatore che non deve memorizzare nella cache un valore letto in precedenza della variabile. –

+0

È utile per il multithreading :) – Partial

+2

volatile non riesce per il multithreading :( – paulm

1

si potrebbe usare

 
#pragma optimize off 
int globalVar 
#pragma optimize on 

ma non so se che funziona solo in Visual Studio (http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx).

Si potrebbe anche dire al compilatore di non ottimizzare a tutti, soprattutto se si sta debug ...

+0

Questo non è compatibile con tutti i compilatori IDE – Partial

+0

ma mi piacerebbe che lo fosse! – radsdau

+0

Su Visual Studio la sintassi è #pragma optimize ("", off) ma per me non impedisce la rimozione della variabile globale in una libreria statica. – gast128

0

Stai usando gcc con gdb? Si è verificato un problema in passato in cui gdb non è riuscito a impostare con precisione i punti di interruzione nei costruttori.

Inoltre, si sta utilizzando un livello di ottimizzazione che consente al compilatore di incorporare i metodi nella definizione della classe.

-2

Come utilizzare la parola chiave volatile? Impedirà al compilatore di troppa ottimizzazione.

0

Ho lo stesso problema di configurazione & su VS2008. Ho scoperto che se dichiari la tua lezione con dllexport non si ottimizzerà.

class __declspec(dllexport) Cxxx 
{ 
. 
} 

Tuttavia, questo genera un sacco di avvertimenti nel mio caso perché devo dichiarare tutte le classi utilizzate in questa classe anche come dllexport.

Tutte le ottimizzazioni sono disattivate (in modalità di debug), tuttavia questo è ottimizzato. Anche volatile/pragma ottimizzare. Sulla variabile globale creata di questa classe (nello stesso file cpp), ecc non funziona.

Appena trovato che dllexport richiede almeno di includere i file di intestazione di queste classi in qualche altro file cpp da exe a lavoro! Pertanto, l'unica opzione è aggiungere un file con chiamate ad alcuni membri statici per ogni classe e aggiungere questo file a tutti i progetti utilizzati in queste classi.

1

è possibile forzare che un oggetto (l'elenco dei tipi) tira alcuni altri oggetti con esso da parzialmente collegando loro prima di costruire il lib statica completa.

Con GNU linker:

ld -Ur -o TypeBundle.o type1.o type2.o type3.o static_list.o 
ld -static -o MyStaticLib.a type_bundle.o other_object.o another_object.o ... 

Pertanto, ogni volta che l'elenco statico fa riferimento codice utilizzando la libreria, l'oggetto completo "TypeBundle.o" otterrà legato nel binario risultante, compreso type1.o, tipo2 .o e type3.o.

Mentre ci si trova, controllare il significato di "-Ur" in the manual.

Problemi correlati