6

Załóżmy, że mam klasy Singleton S w statycznej biblioteki, może to być związane z innymi dynamicznych bibliotek D1 D2 D3class Singleton w statycznej biblioteki

Więc z tego co rozumiem klasa S będzie mieć oddzielny wystąpienie w każdym D1, D2 i D3 i byłoby to prawdą, nawet jeśli nie jest to singleton (podobnie jak globalny). Czy istnieje sposób na uniknięcie wielu kopii klasy S? Nie mogę umieścić singletonu S w innej bibliotece dynamicznej.

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

EDIT: Singletor S jest w osobnej biblioteki statycznej, która łączy ze D1 D2 D3 ... oddzielnie.
Singletor jest przydzielona w stercie, tylko wskaźnik jest statyczna

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

Edit2:

Zrobiłem prosty przypadek testowy, aby sprawdzić rzeczy To makefile próbki (zastąpienie przez .dll. więc) zrobiłem, żeby sprawdzić rzeczy, sprawdziłem to na Ubuntu i Cygwin, oba kompilatory g ++, a zachowanie było inne. Cygwin stworzony 2 różne przedmioty, ale jednak ubuntu Utworzony 1 obiektów

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

jaki jest twój zamiar? Jeśli chcesz kontrolować dostęp do współużytkowanych zasobów, możesz użyć synchronizacji międzyprocesowej, na przykład używając [boost] (http://www.boost.org/doc/libs/1_61_0/doc/html/interprocess/synchronization_mechanisms.html) –

+0

Nie nie chodzi o pamięć współdzieloną między procesami. – tejas

+0

@tejas: dlaczego nie można utworzyć biblioteki DLL w systemie Windows? –

Odpowiedz

2

istnieją dwa przypadek wdrożenia dla singletone.

1, pojedyncza instancja jako wskaźnik, getInstance dynamicznie przydzieli pamięć ze sterty w tym przypadku.

2, pojedyncza instancja jako element statyczny i nie ma miejsca przydzielanie pamięci.

Następujący związek omówiono gdzie pamięć statyczna się: Where are static variables stored (in C/C++)?

W każdym z powyższych realizacji: Jeżeli D1, D2, D3 i D4 znajdują się w tej samej aplikacji, a tym samym samego procesu (na przykład stosowanych w różnych nici) następnie mają ten sam singleton. Jeżeli D1, D2, D3 i D4 należą do innego procesu, to znaczy mają swoją własną przestrzeń pamięci i dlatego nie mają wspólnego tego samego singletonu.

+0

usunąłem ją jako odpowiedź, ponieważ odkryłem, że to zachowanie jest inne – tejas

+0

To niesamowite, że Windows działa w ten sposób! –

+0

Uważam, że ta odpowiedź jest niewłaściwa w MSVC. Używanie funkcji boost_serialization jako biblioteki statycznej polega na utworzeniu swoich singletonów zaplecza (np. Dla informacji o typie) raz na moduł łączący bibliotekę statyczną. To z kolei psuje cały cel tego backendu (niezarejestrowany wyjątek klasy podniesiony) –

5

Jeśli twój dynamiczny linker nie jest uszkodzony, nie powinieneś mieć żadnych problemów. Nawet jeśli każda biblioteka dynamiczna faktycznie zawiera pliki obiektów z biblioteki statycznej S, dynamiczny program ładujący powinien być wystarczająco inteligentny, aby określić, że odpowiada on temu samemu symbolowi i konsekwentnie używać tych samych adresów w całej aplikacji.

W skrócie, jeśli system nie jest uszkodzony ma prawdziwy ładowarka dynamiczny, nie ma tu


Per edycję nie ma problemu, mogę potwierdzić, że powyższe jest tak jak powinno być w miłym świat i sposób, w jaki jest on w systemach uniksopodobnych. Mówisz, że działa na Ubuntu i mogę potwierdzić, że działa tak samo na FreeBSD.

Ale w systemie Windows jest niestety inaczej. Nie masz prawdziwego dynamicznego programu ładującego, takiego jak ld.so, ale potrzebujesz tylko adresów wyeksportowanych funkcji lub danych z biblioteki DLL. W rezultacie każda biblioteka DLL będzie używać własnej kopii singletonu, ponieważ każda z nich będzie zawierała własną kopię kodu i użyje go, ponieważ nie istnieje globalna faza łączenia, aby je scalić.

Co gorsza, nie wyobrażam sobie żadnego prostego rozwiązania: łączenie statyczne i dynamiczne łączenie mają inne zachowanie. Oznacza to, że gdy tylko użyjesz dynamicznego łączenia w systemie Windows, pojedyncza lub dowolna współdzielona informacja, do której można uzyskać dostęp z co najmniej dwóch różnych bibliotek DLL, musi znajdować się w jednym miejscu, co oznacza bibliotekę DLL.

TL/DR: Jeśli twój system ma prawdziwy dynamiczny program ładujący (Unix jak masz), nie musisz martwić się o statyczne lub dynamiczne łączenie, ładowarka (ld.so) będzie o to dbać. W systemie Windows, który nie ma dynamicznego programu ładującego, ale wywołanie API w czasie wykonywania LoadLibrary, wszystkie udostępnione dane muszą znajdować się w jednym i tylko jednym module.

+0

Zaktualizowałem pytanie – tejas

+0

@tejas: i zaktualizowałem odpowiedź ... –