---症状
当我从主机应用程序的子线程加载Dll且主机应用程序关闭时,调用Dll_PROCESS_DETACH
时仅剩下1个线程。这是不好的。这会导致内存泄漏,并且无法执行所需的清除操作。
当我从主机应用程序的MAIN线程加载Dll且主机应用程序关闭时,
调用Dll_PROCESS_DETACH
时,在Dll中创建的所有线程仍在运行。
这很好,因为我可以完成所需的所有清理工作。
我的Dll_PROCESS_ATTACH
没有代码。没有创建线程,没有调用API函数。
-此Dll的用途,用例
我需要一个可以在各种主机应用程序中运行的Dll,我不知道何时 完全是我的Dll加载和卸载。
其中一些主机申请明显 从线程内加载我的Dll,例如该线程正在运行一个脚本,并且该脚本使用了我的Dll的导出功能。
一般的问题是:第一次从主机应用程序的子线程加载Dll时,由于无法调用Dll_PROCESS_DETACH
似乎删除了所有线程,因此无法正确卸载Dll。这不仅会导致内存泄漏,还无法进行一些内部清理工作,停止线程以及进行最终的套接字连接(用于与服务器通信)。
当从主线程(在我的测试主机中)或在它测试的特定主机应用中加载Dll时,所有这些工作正常。
在Visual Studio 17中运行的c ++ Dll调试会话的两个堆栈跟踪。 首先是坏的,从子线程加载Dll。
第二个是好的,从主线程加载了Dll。
// exit stack Dll Dll loaded in subthread ; breakpoint in `Dll_PROCESS_DETACH` This is BAD
DllTest.dll!DllTest_app::~DllTest_app() Line 176 C++
[External Code]
DllTest.dll!DllTest_app::destroy() Line 208 C++
DllTest.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 43 C++
[External Code]
DllTest_test.exe!exit_or_terminate_process(const unsigned int return_code) Line 130 C++
DllTest_test.exe!common_exit(const int return_code, const _crt_exit_cleanup_mode cleanup_mode, const _crt_exit_return_mode return_mode) Line 271 C++
DllTest_test.exe!exit(int return_code) Line 283 C++
[External Code]
// exit stack Dll loaded in mainthread; breakpoint in `Dll_PROCESS_DETACH` This is GOOD
DllTest.dll!DllTest_app::~DllTest_app() Line 175 C++
[External Code]
DllTest.dll!DllTest_app::destroy() Line 208 C++
DllTest.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 43 C++
[External Code]
DllTest_test.exe!DllTestWrap::Unload(int code, int bdeleteerror) Line 139 C++
DllTest_test.exe!DllTestWrap::~DllTestWrap() Line 66 C++
[External Code]
DllTest_test.exe!_execute_onexit_table::__l22::<lambda>() Line 198 C++
DllTest_test.exe!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) & __ptr64,void <lambda>(void) >(__acrt_lock_and_call::__l3::void <lambda>(void) && setup, _execute_onexit_table::__l22::int <lambda>(void) & action, __acrt_lock_and_call::__l4::void <lambda>(void) && cleanup) Line 199 C++
DllTest_test.exe!__acrt_lock_and_call<int <lambda>(void) >(const __acrt_lock_id lock_id, _execute_onexit_table::__l22::int <lambda>(void) && action) Line 882 C++
DllTest_test.exe!_execute_onexit_table(_onexit_table_t * table) Line 222 C++
DllTest_test.exe!common_exit(const int return_code, const _crt_exit_cleanup_mode cleanup_mode, const _crt_exit_return_mode return_mode) Line 211 C++
DllTest_test.exe!exit(int return_code) Line 283 C++
[External Code]
如何实现,即在Dll_PROCESS_DETACH上调用时,无论是从主机应用程序的子线程还是主线程加载Dll,在Dll中创建的所有线程仍在运行并且不会终止。
是否可以通过编译器或链接器设置或替代方法来完成某些工作?
预先感谢您的提示。
答案 0 :(得分:0)
您的应用中似乎有一个线程调用exit()导致调用ExitProcess()API-https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess
如ExitProcess文档中所述,它将终止所有线程,然后使用DLL_PROCESS_DETACH调用DllMain()。
如果终止的线程持有一个互斥锁,则调用ExitProcess也会导致死锁。最后一个执行DLL_PROCESS_DETACH的线程试图获取该互斥锁。