2011-02-07 8 views
5

* Domanda rivisto (vedi sotto) *variabile Global ha più copie su Windows e un singolo su Linux quando compilato sia in exec e condivisa libaray

Ho un file cpp che definisce una variabile globale statica per esempio

Questo file cpp viene compilato in un eseguibile e una libreria condivisa. L'eseguibile può caricare la libreria condivisa in fase di esecuzione.

Se sono su Linux, sembrano esserci due copie di questa variabile. Presumo che uno provenga dall'eseguibile e uno dalla libreria condivisa. Altre piattaforme (HP, Windows) sembrano essere solo una copia.

Cosa controlla questo comportamento su Linux e posso modificarlo? Ad esempio c'è un flag di compilatore o linker che costringerà la versione di questa variabile dalla libreria condivisa a essere uguale a quella dell'eseguibile?

* Revisione della domanda *

Grazie per le risposte finora. Nel riesaminare il problema, in realtà non è il problema indicato sopra. La variabile statica globale sopra ha effettivamente più copie su Windows, quindi nessuna differenza rispetto a quello che vedo su Linux.

Tuttavia, ho un'altra variabile globale (non statica questa volta) che è dichiarata in un file cpp e come esterna in un file di intestazione.

Su Windows questa variabile ha più copie, una nell'eseguibile e una in ogni DLL caricata, e su Linux ne ha solo una. Quindi la domanda è ora su questa differenza. Come posso fare in modo che Linux abbia più copie?

(La logica del mio programma significava il valore della variabile globale statica era dipendente del valore della variabile globale non statico e ho iniziato accusando la variabile sbagliata quale causa dei problemi)

risposta

4

Consiglio vivamente di leggere lo following. In seguito, capirai tutto sulle librerie condivise in Linux. Come detto da altri, la risposta rapida è che la parola chiave static limiterà l'ambito della variabile globale all'unità di traduzione (e quindi, all'eseguibile o alla libreria condivisa). L'utilizzo della parola chiave extern nell'intestazione e la compilazione di un cpp contenente la stessa variabile globale in uno solo dei moduli (exe o dll/so) renderà la variabile globale univoca e condivisa tra tutti i moduli.

EDIT: Il comportamento su Windows non è lo stesso che su Linux quando si utilizza il modello extern perché il metodo di Windows' di caricare le librerie a collegamento dinamico (DLL) non è la stessa ed è fondamentalmente incapaci di collegare variabili globali in modo dinamico (tale che ne esiste solo uno). Se è possibile utilizzare un carico statico della DLL (se non utilizzano LoadLibrary), quindi è possibile utilizzare il seguente:

//In one module which has the actual global variable: 
__declspec(dllexport) myClass myGlobalObject; 
//In all other modules: 
__declspec(dllimport) myClass myGlobalObject; 

Questo renderà il myGlobalObject unica e condivisa tra tutti i moduli che utilizzano la DLL in cui la prima viene utilizzata la versione di cui sopra.

Se si desidera che ogni modulo per avere la propria istanza della variabile globale, quindi utilizzare la parola chiave static, il comportamento sarà lo stesso per Linux o Windows.

Se si desidera un caso unico della variabile globale e richiedono il caricamento dinamico (LoadLibrary o dlopen), si dovrà fare una funzione di inizializzazione di fornire ad ogni DLL caricato con un puntatore alla variabile globale (prima del suo utilizzo) . Dovrai anche tenere un conteggio dei riferimenti (puoi usare uno shared_ptr per quello) in modo che tu possa crearne uno nuovo quando non ne esiste uno, incrementare il conteggio altrimenti, ed essere in grado di cancellarlo quando il conteggio va a zero quando le DLL sono essere scaricato.

+0

Il comportamento di Windows è stato dichiarato in modo errato. Vedi la domanda rivista per la differenza effettiva tra Windows e Linux. – Reuben

+0

Vedere la mia risposta aggiornata. Inoltre, leggendo l'articolo a cui mi sono collegato spiegherò perché Linux è in grado di raggiungere questo obiettivo e perché è difficile e apparentemente impossibile in Windows. –

+0

La risposta era nella sezione 2.2 del documento collegato. A causa della versione precedente del compilatore mi sono limitato a e posso cambiare la fonte in cui è stata dichiarata la variabile, ho finito con l'utilizzo delle mappe di esportazione (sezione 2.2.5) – Reuben

1

Cosa compilatore ha fatto utilizzare su ciascuna di queste piattaforme? Il comportamento che stai descrivendo per Linux sarebbe quello che mi aspetterei, il globale statico è solo locale a quel particolare file in fase di compilazione.

+0

Il comportamento di Windows è stato dichiarato in modo non corretto. Vedi la domanda rivista per la differenza effettiva tra Windows e Linux. di Windows compilatore è MS Visual Studio 2003 Linux è gcc 3.3.3 HP è aC++/ANSI C B3910B A.06.01 [5 gennaio 2005] – Reuben

+0

@Reuben: Questi sono molto vecchi compilatori, si dovrebbe prendere in considerazione un aggiornamento per entrambe le piattaforme . Non penso che cambierà il comportamento però. –

0

Non so su HPUX, ma su Windows, se si dispone di un exe e una DLL, e ognuno di essi dichiara variabili globali, allora ci saranno due variabili distinte. Se stai ricevendo una sola variabile, una immagine deve importare la variabile dall'altra.

3

Il qualificatore static applicato a una variabile del namespace indica che l'ambito della variabile è l'unità di traduzione. Ciò significa che se tale variabile è definita in un'intestazione e la includi da più file .cpp, ne otterrai una copia per ciascuno. Se si desidera una singola copia, contrassegnarla come extern (e non static) nell'intestazione, definirla in una singola unità di traduzione e collegarla nell'eseguibile o nella libreria (ma non in entrambi).

Problemi correlati