进程显式加载Dll释放时卡在FreeLibrary
DLL隐式加载时没问题,进程可以正常退出。显式加载时就会卡在FreeLibrary,一运行至FreeLibrary调试器里的调用堆栈就被清空了,进程没有退出,但也不报错,经排查不是线程、指针之类的低级错误,跟自己代码没关系
一种可能是DllMain死锁,但里面什么都没做
switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH:break; case DLL_THREAD_ATTACH:break; case DLL_THREAD_DETACH:break; case DLL_PROCESS_DETACH:break; }
msdn的文档DllMain entry point
一篇求助贴
一篇博文
一种可能是winsocket,DLL里用到了win socket, 一旦建立过连接退出进程就卡FreeLibrary,没有建立连接或者连接失败就没问题
msdn的文档说WSACleanup可能会导致DllMain死锁,但我这并不是
尝试通过windbg抓异常,跟VS debug一样的,也是抓不到东西。通过windbg看依赖项
ModLoad: 00007ff7`f5a80000 00007ff7`f5b36000 image00007ff7`f5a80000
ModLoad: 00007ffc`39990000 00007ffc`39ba7000 ntdll.dll
ModLoad: 00007ffc`38500000 00007ffc`385c4000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ffc`37020000 00007ffc`373c6000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ffc`38ed0000 00007ffc`3972b000 C:\Windows\System32\SHELL32.dll
ModLoad: 00007ffc`36e60000 00007ffc`36efa000 C:\Windows\System32\msvcp_win.dll
ModLoad: 00007ffc`36f00000 00007ffc`37011000 C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ffb`859b0000 00007ffb`85f65000 D:\Release\Qt5Gui.dll
ModLoad: 00000000`6ae70000 00000000`6b3ee000 D:\Release\Qt5Core.dll
ModLoad: 00000000`6b3f0000 00000000`6b945000 D:\Project\RayoptoDetector\x64\Release\Qt5Widgets.dll
ModLoad: 00007ffc`37cc0000 00007ffc`37e6e000 C:\Windows\System32\USER32.dll
ModLoad: 00007ffc`36cd0000 00007ffc`36cf6000 C:\Windows\System32\win32u.dll
ModLoad: 00007ffc`37840000 00007ffc`37869000 C:\Windows\System32\GDI32.dll
ModLoad: 00007ffc`37450000 00007ffc`37568000 C:\Windows\System32\gdi32full.dll
ModLoad: 00000000`6ae10000 00000000`6ae63000 D:\Release\Qt5Svg.dll
ModLoad: 00007ffc`38640000 00007ffc`387e0000 C:\Windows\System32\ole32.dll
ModLoad: 00007ffc`38170000 00007ffc`384f9000 C:\Windows\System32\combase.dll
ModLoad: 00007ffc`37ac0000 00007ffc`37bd7000 C:\Windows\System32\RPCRT4.dll
ModLoad: 00007ffc`0f8a0000 00007ffc`0f98f000 C:\Windows\SYSTEM32\MSVCR120.dll
ModLoad: 00007ffc`0bea0000 00007ffc`0bf46000 C:\Windows\SYSTEM32\MSVCP120.dll
ModLoad: 00007ffc`36910000 00007ffc`3691a000 C:\Windows\SYSTEM32\VERSION.dll
ModLoad: 00007ffb`7e2f0000 00007ffb`80e58000 D:\Release\opencv_world310.dll
ModLoad: 00007ffc`37790000 00007ffc`37837000 C:\Windows\System32\msvcrt.dll
ModLoad: 00007ffc`37be0000 00007ffc`37cb7000 C:\Windows\System32\OLEAUT32.dll
ModLoad: 00007ffc`30160000 00007ffc`3020b000 C:\Windows\SYSTEM32\UxTheme.dll
ModLoad: 00007ffc`302a0000 00007ffc`302cb000 C:\Windows\SYSTEM32\dwmapi.dll
ModLoad: 00007ffc`38db0000 00007ffc`38ea9000 C:\Windows\System32\COMDLG32.dll
ModLoad: 00007ffc`37f30000 00007ffc`38023000 C:\Windows\System32\shcore.dll
ModLoad: 00007ffc`38030000 00007ffc`3808e000 C:\Windows\System32\SHLWAPI.dll
ModLoad: 00007ffc`387e0000 00007ffc`38893000 C:\Windows\System32\ADVAPI32.dll
ModLoad: 00007ffc`376e0000 00007ffc`37788000 C:\Windows\System32\sechost.dll
ModLoad: 00007ffc`36e30000 00007ffc`36e58000 C:\Windows\System32\bcrypt.dll
ModLoad: 00007ffc`1cb40000 00007ffc`1cbf3000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.22621.2506_none_b43bab19638c9595\COMCTL32.dll
ModLoad: 00007ffc`161a0000 00007ffc`161cb000 C:\Windows\SYSTEM32\MSVFW32.dll
ModLoad: 00007ffc`17140000 00007ffc`1715a000 C:\Windows\SYSTEM32\AVICAP32.dll
ModLoad: 00007ffc`02af0000 00007ffc`02b14000 C:\Windows\SYSTEM32\AVIFIL32.dll
ModLoad: 00007ffc`2a8f0000 00007ffc`2a924000 C:\Windows\SYSTEM32\WINMM.dll
ModLoad: 00007ffb`af020000 00007ffb`af03e000 C:\Windows\SYSTEM32\MSACM32.dll
ModLoad: 0000019e`cd210000 0000019e`cd244000 C:\Windows\SYSTEM32\WINMM.dll
ModLoad: 00007ffc`38d30000 00007ffc`38da1000 C:\Windows\System32\WS2_32.dll
ModLoad: 00007ffc`0cdf0000 00007ffc`0ce0e000 C:\Windows\SYSTEM32\MPR.dll
(52d8.5394): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffc`39a6b784 cc int 3
0:000> g
ModLoad: 00007ffc`37a80000 00007ffc`37ab1000 C:\Windows\System32\IMM32.DLL
ModLoad: 00007ffc`36460000 00007ffc`3646c000 C:\Windows\SYSTEM32\CRYPTBASE.DLL
ModLoad: 00007ffc`373d0000 00007ffc`3744a000 C:\Windows\System32\bcryptPrimitives.dll
ModLoad: 00007ffb`d7f50000 00007ffb`d809f000 D:\Release\platforms\qwindows.dll
ModLoad: 00007ffc`35d90000 00007ffc`35da8000 C:\Windows\SYSTEM32\kernel.appcore.dll
ModLoad: 00007ffc`34bd0000 00007ffc`354c6000 C:\Windows\SYSTEM32\windows.storage.dll
ModLoad: 00007ffc`34a90000 00007ffc`34bce000 C:\Windows\SYSTEM32\wintypes.dll
ModLoad: 00007ffc`36c00000 00007ffc`36c26000 C:\Windows\SYSTEM32\profapi.dll
ModLoad: 00007ffc`33f50000 00007ffc`341c4000 C:\Windows\system32\dwrite.dll
ModLoad: 00007ffb`f1d30000 00007ffb`f1d78000 D:\Release\MyDll.dll
ModLoad: 00007ffb`e8cf0000 00007ffb`e8d13000 C:\Windows\SYSTEM32\VCOMP120.DLL
ModLoad: 00007ffb`e81b0000 00007ffb`e81ef000 D:\Release\imageformats\qjpeg.dll
ModLoad: 00007ffc`0b2f0000 00007ffc`0b2fc000 D:\Release\imageformats\qsvg.dll
ModLoad: 00007ffc`39730000 00007ffc`39881000 C:\Windows\System32\MSCTF.dll
ModLoad: 00007ffc`37e80000 00007ffc`37f30000 C:\Windows\System32\clbcatq.dll
ModLoad: 00007ffc`03eb0000 00007ffc`03f0e000 C:\Windows\system32\dataexchange.dll
ModLoad: 00007ffc`26c70000 00007ffc`26ef7000 C:\Windows\system32\twinapi.appcore.dll
clientcore\windows\advcore\ctf\uim\tim.cpp(800)\MSCTF.dll!00007FFC397465D9: (caller: 00007FFC3974720C) LogHr(1) tid(5394) 8007029C 出现声明故障。
clientcore\windows\advcore\ctf\uim\tim.cpp(800)\MSCTF.dll!00007FFC397465D9: (caller: 00007FFC3974720C) LogHr(2) tid(5394) 8007029C 出现声明故障。
ModLoad: 00007ffc`27140000 00007ffc`2728a000 C:\Windows\SYSTEM32\textinputframework.dll
ModLoad: 00007ffc`04060000 00007ffc`040ab000 C:\Windows\system32\ApplicationTargetedFeatureDatabase.dll
ModLoad: 00007ffc`36210000 00007ffc`36279000 C:\Windows\system32\mswsock.dll
只要多了这个C:\Windows\system32\mswsock.dll就不行
VS debug单步调试,进入FreeLibrary,卡在了C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\crtdll.c的这个地方:
__declspec(noinline) BOOL __cdecl __DllMainCRTStartup( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { ... if ( (dwReason == DLL_PROCESS_DETACH) || (dwReason == DLL_THREAD_DETACH) ) { if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) { //单步进去 retcode = FALSE ; } if ( retcode && _pRawDllMain ) { retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved); } } } __except ( __CppXcptFilter(GetExceptionCode(), GetExceptionInformation()) ) { retcode = FALSE; } } __finally ... } BOOL WINAPI _CRT_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { ... else if ( dwReason == DLL_PROCESS_DETACH ) { ... /* cache the function to call. */ function_to_call = (_PVFV) DecodePointer(*onexitend); /* mark the function pointer as visited. */ *onexitend = (_PVFV)EncodePointer(NULL); /* call the function, which can eventually change __onexitbegin and __onexitend */ (*function_to_call)(); //该函数不返回 onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin); onexitend_new = (_PVFV *) DecodePointer(__onexitend); ... }
调试看上面的function_to_call,刚好指向一个单例类的析构函数,这个类里面开了一个线程,就是这里了!卡在了std::thread::join()
我这里是常规的线程控制,看着没问题
void MyClass::StopThread() { m_runningFlag = fale; if (thread->joinable()) thread->join(); ... } void MyClass::ThreadFunc() { while(m_runningFlag) { ... } }
单例类如下
virtual MyClass::~MyClass()
{
StopThread();
}
static MyClass* GetInstance()
{
static MyClass _instance;
return &_instance;
}
难道是因为静态变量,在显式调用DLL时显现出来了,隐式调用静态变量的释放时机不同?
改为在FreeLibrary之前停止线程就可以了
基于 VS2013