Как заставить порядок разрушения статических объектов в разных библиотеках? - PullRequest
4 голосов
/ 16 мая 2009

У меня есть 2 статические объекты в 2 разных библиотеках :

Объект Ресурсы (который является одноэлементным) и объект Пользователь . Пользователь объекта в своем деструкторе должен получить доступ к ресурсам объекта.

Как заставить Ресурсы объекта не уничтожаться до объекта Пользователь?

Ответы [ 4 ]

3 голосов
/ 17 мая 2009

Если вы можете поместить эти 2 глобальные переменные в одну и ту же DLL, это не та история. Как сказал Джем в своем ответе, порядок отсоединения DLL не гарантируется системой. Поэтому у вас могут быть большие проблемы при наличии двух отдельных Dll. Я не гуру системы Windows, но, посмотрев в Google, я обнаружил блоггеров msdn, которые говорят, что у них возникла та же проблема, но нет хорошего решения для ее решения.

Если вы можете поместить их в одну и ту же DLL, по моему мнению, решение проще, в этом случае вам не нужно решать проблему «негарантированного порядка отключения DLL» (насколько я понимаю, неразрешимая) .
Но тогда вам все еще нужно решить новую проблему: порядок уничтожения глобальных переменных не гарантируется языком c ++. Но к этому можно обратиться:

вам нужно использовать какую-то контрольную маркировку. boost :: shared_ptr может сделать свое дело.

Объявите его глобальным и определите его так:

boost::shared_ptr my_resource_ptr ( new Resource() ); // new operator is important here!

Затем вам нужно изменить реализацию вашего пользователя на store его собственный shared_ptr:

class User
{
    ...
    boost::share_ptr a_resource_ptr;
    ...
};

До тех пор, пока все ваши экземпляры User не будут уничтожены, они будут «сохранять» экземпляр Resource и, таким образом, предотвращать его преждевременное удаление, даже если глобальный shared_ptr мог быть уничтожен.
Последний экземпляр пользователя, который будет уничтожен, (косвенно) удалит экземпляр ресурса.

Независимо от того, какой счетчик ссылок вы используете, ComPtr, ваш собственный, это должно сработать.

2 голосов
/ 16 мая 2009

Глобальные объекты уничтожаются при выгрузке их соответствующей DLL. Так как ваша dll 'User', вероятно, зависит от вашей dll 'Resource', у вас возникли проблемы: 'resource' всегда будет уничтожен до 'user'.

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

1 голос
/ 17 мая 2009

В случае, если вы действительно хотите получить 2 отдельных Dlls, у меня может быть несколько советов для вас: вы можете рассмотреть возможность использования FreeLibrary() из Windows API. Как указано msdn FreeLibrary() уменьшает счетчик ссылок для Dll, который выгружается, когда счетчик достигает 0.

Недостаток: использование FreeLibrary() подразумевает, что вы загружаете его с LoadLibrary() ( msdn link ), а вызов функции из этой библиотеки подразумевает, что вы используете функцию GetProcAddress(), что может привести к действительно уродливому код. И это также может означать некоторые изменения в вашем коде - например, получение глобальной переменной для функций Dll для хранения адреса каждой функции ...

Если вы хотите реализовать это:

  1. вы должны загрузить и освободить библиотеку из функции main() вашего процесса,
  2. , а также загрузить и освободить библиотеку из библиотеки DLL, реализующей класс User. Реализуйте его в функции DllMain() для этого Dll, когда причина DLL_PROCESS_DETACH (см. Ссылку mdsn на DllMain .

Таким образом, она будет выгружать библиотеку «Ресурс» только после того, как библиотека «Пользователь» закончит с ней.

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

PS: У меня есть второй ответ на ваш вопрос, чтобы получить осмысленное разделение между двумя ответами, когда я (пытаюсь) детализировать оба из них. Я не хочу, чтобы вы их перепутали и запутались ...

1 голос
/ 16 мая 2009

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

...