6

Предположим, что у меня есть класс синглтон S в статической библиотеке, это может быть связано с другими динамическими библиотеками D1 D2 D3,Singleton класс в статической библиотеке

Так от того, что я понимаю, класс S будет иметь отдельный экземпляр в каждом D1, D2 и D3, и это было бы правдой, даже если оно не является одиночным (как глобальное)

Есть ли способ предотвратить множественные копии класса S? Я не могу поместить синглтон S в другую динамическую библиотеку.

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

EDIT: Одноэлементный S находится в отдельной статической библиотеки, которая связывает с D1 D2 D3 ... отдельно.
Одноэлементный выделяется в куче, только указатель статична

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

Edit2:

Я сделал простой тест, чтобы проверить вещи Это образец Makefile (замените .dll на. так что я сделал, чтобы проверить все, я проверил его на Ubuntu и Cygwin, как компиляторы g ++, так и поведение было другим. cygwin создал 2 разных объекта, но ubuntu создал 1 объект

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

Каково ваше намерение? Если вы хотите контролировать доступ к общим ресурсам, вы можете использовать межпроцессную синхронизацию, например, используя [boost] (http://www.boost.org/doc/libs/1_61_0/doc/html/interprocess/synchronization_mechanisms.html) –

+0

Нет это не об общей памяти между процессами. – tejas

+0

@tejas: почему вы не можете сделать S DLL на Windows? –

ответ

2

Есть два случая реализации для одиночного.

1, единственный экземпляр как указатель, getInstance будет динамически выделять память из кучи в этом случае.

2, один экземпляр как статический член и не происходит выделения памяти.

Следующая ссылка обсуждает, где это статическая память расположена по адресу: Where are static variables stored (in C/C++)?

В любом из выше реализации: Если D1, D2, D3 и D4 находятся в одном приложении и, таким образом, тот же процесс (например, используемые в разных потоках), то они имеют одинаковый синглтон. Если D1, D2, D3 и D4 принадлежат к разному процессу, то есть они имеют собственное пространство памяти и, таким образом, не имеют одинакового синглтона.

+0

, я удалил его как ответ, поскольку обнаружил, что поведение отличается от – tejas

+0

. Удивительно, что Windows работает таким образом! –

+0

Я нашел этот ответ ошибочным в MSVC. Использование boost_serialization в качестве статической библиотеки происходит для создания экземпляров его бэкэндов (например, для информации типа) один раз на модуль, связывающий статическую библиотеку. Это, в свою очередь, нарушает всю цель этого бэкэнда (исключение незарегистрированного класса поднято) –

5

Если ваш динамический компоновщик не сломан, у вас не должно быть никаких проблем. Даже если каждая динамическая библиотека фактически содержит объектные файлы из статической библиотеки S, динамический загрузчик должен быть достаточно умным, чтобы определить, что они соответствуют одному и тому же символу, и последовательно использовать одинаковые адреса во всем приложении.

Короче говоря, если ваша система не нарушена имеет истинный динамический загрузчик, нет никаких проблем здесь


За ваши изменения, я подтверждаю, что выше, является способом, которым это должно быть в хорошем мира и того, как это делается в Unix-подобных системах. Вы говорите, что это работает на Ubuntu, и я могу подтвердить, что это работает на FreeBSD.

Но, к сожалению, в Windows это не так. У вас нет реального динамического загрузчика, такого как ld.so, но вам нужны только адреса экспортируемых функций или данных из DLL. В результате каждая DLL будет использовать свою собственную копию синглтона, потому что каждая из них будет содержать свою собственную копию кода и использовать ее, потому что нет глобальной фазы связывания для ее объединения.

Что еще хуже, так это то, что я не могу представить себе простого обходного пути: статическая привязка и динамическое связывание имеют полное поведение по-разному. Это означает, что как только вы будете использовать динамическую компоновку в Windows, одноэлемент или любые общие данные, к которым можно получить доступ, по крайней мере, от двух разных DLL, должны находиться в одном месте, то есть в DLL.

TL/DR: Если ваша система имеет настоящий динамический загрузчик (например, Unix), вам не нужно беспокоиться о статической или динамической компоновке, то загрузчик (ld.so) позаботится об этом. В Windows, у которой нет динамического загрузчика, а во время выполнения вызова API LoadLibrary, любые общие данные должны находиться в одном и только одном модуле.

+0

У меня есть вопрос – tejas

+0

@tejas: и я обновил ответ ... –

Смежные вопросы