2009-05-16 5 views
4

У меня 2 статические объекты в различных библиотек DLL:Как заставить порядок уничтожения статических объектов в разных dll?

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

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

+0

Есть ли способ изменить реализацию? Или 2 dll предоставляются третьей стороной? –

+0

Я могу переместить определение 2 статических объектов в одну и ту же DLL, но не в том же cpp. Может ли это помочь? –

ответ

2

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

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

+1

Arf, так что на самом деле вы имеете в виду, что DLL может быть разгружена, а не вся глобальная переменная разрушена? : / –

1

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

3

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

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

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

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

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

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

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

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

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

1

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

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

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

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

Таким образом, он будет выгрузить библиотеку «Ресурс» только один раз «User» библиотеки имеют отделку с ним.

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

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