由于 FreeLibraryAndExitThread 内部会使用 ExitThread 终止调用线程,如果调用线程是用_beginthreadex创建的,可能会造成 _beginthreadex 分配的资源得不到释放。解决方法是使用 CreateThread 创建新线程,在新线程中首先等待 _beginthreadex 创建的线程正常终止,然后在调用 FreeLibraryAndExitThread , 示例代码如下:
#include <process.h>
#include <windows.h>
static HMODULE __hModule = NULL;
static HANDLE __hDllMainThread = NULL;
// 在这个函数中做实际工作,这个函数返回后自动卸载当前DLL
extern unsigned Main(HMODULE hModule);
static DWORD WINAPI __FreeLibraryThread(LPVOID lpParam) {
::WaitForSingleObject(__hDllMainThread, INFINITE);
::CloseHandle(__hDllMainThread);
::FreeLibraryAndExitThread(__hModule, 0);
return 0;
}
/* when this thread exit, the DLL will be free */
static unsigned __stdcall __DllMainThread(void *lpParam) {
unsigned ret = EXIT_FAILURE;
__try {
__try {
unsigned ret = Main(__hModule);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
;
}
}
__finally {
HANDLE h = ::CreateThread(NULL, 0, __FreeLibraryThread, 0, 0, NULL);
if (h != NULL) {
::CloseHandle(h);
}
else {
;
}
}
return ret;
}
// DLL加载时创建线程,并在线程中调用Main函数。
// Main函数返回后,自动卸载DLL。
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
__hModule = hModule;
__hDllMainThread = (HANDLE)::_beginthreadex(NULL, 0, __DllMainThread, NULL, 0, NULL);
if (__hDllMainThread == NULL) {
return FALSE;
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}