6

Supponiamo che ho una classe Singleton S in una libreria statica, questo potrebbe essere collegato con le altre librerie dinamiche D1 D2 D3,classe Singleton in una libreria statica

Quindi, da quello che ho capito la classe S avrà un separato istanza in ogni D1, D2 e ​​D3 e questo sarebbe vero anche se non è un singleton (come globale)

Esiste un modo per prevenire copie multiple della classe S? Non riesco a mettere il singleton S in un'altra libreria dinamica.

    Executable 
       / | \ \ 
       D1 D2 D3 D4 
       | | | 
       S S S 

EDIT: Il Singleton S è in una libreria statica separata che si collega con la D1 D2 D3 ... a parte.
Il singleton viene allocato nell'heap, solo il puntatore è statico

static s::instance() 
{ 
    static smart_ptr<S> ptr = NULL; 
    if(ptr == NULL) ptr = new S; 
    return ptr; 
} 

Edit2:

Ho fatto un semplice caso di test per controllare le cose Questo è un makefile di esempio (sostituire dll. così) ho fatto il check-out, l'ho controllato su Ubuntu e Cygwin, entrambi i compilatori g ++ e il comportamento era diverso. cygwin creato 2 oggetti diversi ma ma ubuntu creata 1 oggetti

all: dynamic1 dynamic2 main 

static: static.cpp 
    g++ -c -fPIC static.cpp -o obj/static.o 
    ar rvs lib/static.a obj/static.o 

dynamic1: static dynamic1.cpp 
    g++ -fPIC -shared dynamic1.cpp lib/static.a -o lib/libdynamic1.dll 

dynamic2: static dynamic2.cpp 
    g++ -fPIC -shared dynamic2.cpp lib/static.a -o lib/libdynamic2.dll 

main: dynamic1 dynamic2 main.cpp 
    g++ --std=c++11 main.cpp -ldynamic1 -ldynamic2 -o lib/main -L./lib 
+0

qual è la vostra intenzione? Se si desidera controllare l'accesso alle risorse condivise, è possibile utilizzare la sincronizzazione dell'interpretazione, ad esempio utilizzando [boost] (http://www.boost.org/doc/libs/1_61_0/doc/html/interprocess/synchronization_mechanisms.html) –

+0

No non si tratta di memoria condivisa tra processi. – tejas

+0

@tejas: perché non puoi creare una DLL su Windows? –

risposta

2

ci sono due caso di realizzazione del Singletone.

1, istanza singola come puntatore, in questo caso getInstance allocherà dinamicamente la memoria dall'heap.

2, singola istanza come membro statico e non si verifica alcuna allocazione di memoria.

La seguente Link discute dove è la memoria statica situato: Where are static variables stored (in C/C++)?

In qualsiasi sopra attuazione: Se D1, D2, D3 e D4 sono in stessa applicazione e quindi stesso processo (utilizzati in diversi thread), quindi condividono lo stesso singleton. Se D1, D2, D3 e D4 appartengono a processi diversi, cioè hanno il proprio spazio di memoria e quindi non condividono lo stesso singleton.

+0

l'ho rimosso come risposta in quanto ho scoperto che il comportamento è diverso – tejas

+0

è sorprendente che Windows funzioni in questo modo! –

+0

Ho trovato questa risposta errata in MSVC. Usando boost_serialization come libreria statica accade di istanziare i suoi singleton backend (ad esempio per informazioni sul tipo) una volta per modulo che collega la libreria statica. Questo a sua volta rompe l'intero scopo di questo backend (eccezione di classe non registrata sollevata) –

5

Se il tuo linker dinamico non è rotto, non dovresti avere problemi. Anche se ogni libreria dinamica contiene effettivamente i file oggetto dalla libreria statica S, il caricatore dinamico dovrebbe essere abbastanza intelligente da determinare che corrispondono allo stesso simbolo e utilizzare in modo coerente gli stessi indirizzi nell'intera applicazione.

In breve, se il sistema non è rotto ha un vero caricatore dinamico, non v'è alcun problema qui


Per la tua modifica, confermo che sopra è il modo in cui dovrebbe essere in una bella mondo e il modo in cui è in sistemi simil-Unix. Dici che funziona su Ubuntu, e posso confermare che funziona allo stesso modo su FreeBSD.

Ma su Windows, purtroppo è diverso. Non hai un vero caricatore dinamico come ld.so ma hai solo bisogno di indirizzi di funzioni o dati esportati dalla DLL. Di conseguenza, ogni DLL utilizzerà la propria copia del singleton, poiché ognuna conterrà la propria copia del codice e la userà perché non esiste una fase di collegamento globale per unirla.

Ciò che è ancora peggio è che non riesco a immaginare alcuna soluzione semplice: il collegamento statico e il collegamento dinamico hanno un comportamento completamente diverso. Ciò significa che non appena si utilizza il collegamento dinamico su Windows, un singolo o tutti i dati condivisi a cui è possibile accedere da almeno due DLL diverse devono risiedere in un'unica posizione, ovvero una DLL.

TL/DR: Se il tuo sistema ha un vero caricatore dinamico (come Unix), non devi preoccuparti del collegamento statico o dinamico, il caricatore (ld.so) si prenderà cura di esso. Su Windows, che non ha un caricatore dinamico ma una chiamata API LoadLibrary in fase di esecuzione, qualsiasi dato condiviso deve risiedere in un solo modulo.

+0

Ho aggiornato la domanda – tejas

+0

@tejas: e ho aggiornato la risposta ... –