Функция ExitProcess, в свою очередь, известна тем, что сначала останавливает все потоки, кроме вызывающего (используя NtTerminateProcess), а потом вызывает EntryPoint для всех dll с флагом DLL_PROCESS_DETACH. В С++ обычно точка входа называется DllMainCRTStartup. DllMainCRTStartup вызывает функцию DllMain и после нее все деструкторы глобальных объектов, расположенных в DLL.
Разумеется, что после удаления некоторого количества потоков, отличного от нуля, выполнение любого кода становится чрезвычайно опасным мероприятием, чреватым дедлоками и крешами. Некоторые комрады также утверждают, что после вызова ExitProcess перестают работать критические секции, и случаются многие другие Ужасные Вещи.
Поэтому, популярный паттерн использования DLL_PROCESS_DETACH выглядит так:
BOOL WINAPI DllMain( |
_Winnie C++ Colorizer |
Параметр lpvReserved описан в MSDN следующим образом:
If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if FreeLibrary has been called or the DLL load failed and non-NULL if the process is terminating.
(с) MSDN
В случае использования С++, код нашей идеальной Dll должен выглядеть так:
static std::auto_ptr<CMyDll> g_myDll; |
_Winnie C++ Colorizer |
В приведенном коде нет особых проблем, но нельзя упускать тот факт, что наша идеальная dll может подключать и, как правило, подключает множество статических библиотек. Которые вполне могут содержать глобальные переменные-объекты.
Выводы крайне тривиальны: использование глобальных переменных-объектов - есть зло, особенно в статических библиотеках. Но если вы уже разрабатываете статическую библиотеку на С++ с глобальными переменными внутри, стоит предоставить функцию для их корректного фатального освобождения, с семантикой, аналогичной g_myDll.release().
No comments:
Post a Comment