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

StackOverflow https://stackoverflow.com/questions/872143

  •  22-08-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

Другие советы

Если вы можете поместить эти две глобальные переменные в одну и ту же 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!

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top