卸载ACE动态库导致句柄泄漏问题
生活随笔
收集整理的這篇文章主要介紹了
卸载ACE动态库导致句柄泄漏问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ACE動態庫在windows程序中通過LoadLibrary和FreeLibrary反復加載和卸載后,發現內存和句柄上漲嚴重,查看動態庫的dllmain函數,發現未調用到ace初始化方法ACE::init(),因此加載動態庫后,顯式調用init,卸載前顯式fini,內存和句柄果然就沒有漲了,但出現了一個新問題,在加載到500多次以后,出現了動態庫文件無法打開錯誤,通過更新ACE最新的6.2.0版本的庫,發現問題依然存在!
前面成功的500多次加載和卸載ace庫,都未看到句柄或者內存泄露現象,突然出現不能加載,問題開始有點難以理解了。
查看ace初始化函數的實現代碼,包含了對對象管理器單例對象的初始化操作:
int ACE::init (void) {// Don't use ACE_TRACE, because Object_Manager might not have been// instantiated yet.// ACE_TRACE ("ACE::init");++ACE::init_fini_count_;return ACE_Object_Manager::instance ()->init (); }
到ACE_Object_Manager::init里注釋代碼,也未果;由于每次都是在500多次加載后失敗,因此嘗試init后不調用fini,果然到100多次后問題就出現了,看來還是和資源未釋放完全相關的。在退出函數fini里注釋代碼,希望能定位到影響問題出現概率的那行代碼從而找到相關的資源信息,把fini函數如下代碼注釋后,問題概率加大:
// Close the main thread's TSS, including its Log_Msg instance.ACE_OS::cleanup_tss (1 /* main thread */);很快可以想到是tss資源泄漏了,通過在tss資源申請的系統函數TlsAlloc里增加斷點,定位到資源申請的位置: ACEd.dll!ACE_OS::thr_keycreate_native(unsigned long * key=0x00ab6220, void (void *)* dest=0x00000000) Line 4791 C++ACEd.dll!ACE_OS::thr_keycreate(unsigned long * key=0x00ab6220, void (void *)* dest=0x00000000) Line 4835 + 0xd bytes C++ACEd.dll!ACE_Thread::keycreate(unsigned long * keyp=0x00ab6220, void (void *)* destructor=0x00000000) Line 23 + 0xd bytes C++ACEd.dll!ACE_Threading_Helper<ACE_Thread_Mutex>::ACE_Threading_Helper<ACE_Thread_Mutex>() Line 43 + 0xb bytes C++ACEd.dll!ACE_Service_Config::ACE_Service_Config(bool ignore_static_svcs=true, unsigned int size=1024, int signum=0) Line 372 + 0x6d bytes C++ > ACEd.dll!ACE_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::ACE_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>() Line 15 C++ACEd.dll!ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>() Line 19 + 0x16 bytes C++ACEd.dll!ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::instance() Line 184 + 0x27 bytes C++ACEd.dll!ACE_Service_Config::singleton() Line 327 C++ACEd.dll!ACE_Service_Config::current() Line 424 + 0x5 bytes C++ACEd.dll!ACE_Service_Config::instance() Line 87 C++ACEd.dll!ACE_Service_Config::insert(ACE_Static_Svc_Descriptor * stsd=0x102609bc) Line 332 + 0x9 bytes C++ACEd.dll!ACE_Static_Svc_ACE_Naming_Context::ACE_Static_Svc_ACE_Naming_Context() Line 650 + 0x18 bytes C++ACEd.dll!`dynamic initializer for 'ace_static_svc_ACE_Naming_Context''() Line 650 + 0xd bytes C++
以及:
ACEd.dll!ACE_OS::thr_keycreate_native(unsigned long * key=0x00ab9648, void (void *)* dest=0x1000b2ad) Line 4791 C++ACEd.dll!ACE_OS::thr_keycreate(unsigned long * key=0x00ab9648, void (void *)* dest=0x1000b2ad) Line 4835 + 0xd bytes C++ > ACEd.dll!ACE_TSS_Cleanup::tss_keys() Line 993 + 0x14 bytes C++ACEd.dll!ACE_TSS_Cleanup::thread_use_key(unsigned long key=7) Line 941 + 0xc bytes C++ACEd.dll!ACE_OS::thr_setspecific(unsigned long key=7, void * data=0x00ab9688) Line 5049 C++ACEd.dll!ACE_Thread::setspecific(unsigned long key=7, void * value=0x00ab9688) Line 42 + 0xd bytes C++ACEd.dll!ACE_Threading_Helper<ACE_Thread_Mutex>::set(void * p=0x00ab9688) Line 54 + 0xf bytes C++ACEd.dll!ACE_Service_Config::ACE_Service_Config(bool ignore_static_svcs=true, unsigned int size=1024, int signum=0) Line 386 C++ACEd.dll!ACE_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::ACE_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>() Line 15 C++ACEd.dll!ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>() Line 19 + 0x16 bytes C++ACEd.dll!ACE_Unmanaged_Singleton<ACE_Service_Config,ACE_Recursive_Thread_Mutex>::instance() Line 184 + 0x27 bytes C++ACEd.dll!ACE_Service_Config::singleton() Line 327 C++ACEd.dll!ACE_Service_Config::current() Line 424 + 0x5 bytes C++ACEd.dll!ACE_Service_Config::instance() Line 87 C++ACEd.dll!ACE_Service_Config::insert(ACE_Static_Svc_Descriptor * stsd=0x102609bc) Line 332 + 0x9 bytes C++ACEd.dll!ACE_Static_Svc_ACE_Naming_Context::ACE_Static_Svc_ACE_Naming_Context() Line 650 + 0x18 bytes C++ACEd.dll!`dynamic initializer for 'ace_static_svc_ACE_Naming_Context''() Line 650 + 0xd bytes C++msvcr90d.dll!0045c02c()通過觀察,發現第二次申請的tss資源在fini函數調用后并沒有釋放掉,導致tss資源出現了泄漏,申請代碼如下: ACE_TSS_Keys * ACE_TSS_Cleanup::tss_keys () {if (this->in_use_ == ACE_OS::NULL_key){ACE_TSS_CLEANUP_GUARD// Double-check;if (in_use_ == ACE_OS::NULL_key){// Initialize in_use_ with a new key.if (ACE_OS::thr_keycreate (&in_use_,&ACE_TSS_Cleanup_keys_destroyer)){ACE_ASSERT (false);return 0; // Major problems, this should *never* happen!}}}
因此,一個解決的辦法就是在Cleanup的析構函數中,將in_use_對應的tss資源釋放: ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void) {free_key(in_use_);in_use_ = 0; }
重新編譯ACE庫后,經過長時間測試問題不再出現!
總結
以上是生活随笔為你收集整理的卸载ACE动态库导致句柄泄漏问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringIoC和SpringMVC的
- 下一篇: Xcode各版本官方下载及百度云盘下载,