卸载ACE动态库导致句柄泄漏问题
ACE動(dòng)態(tài)庫(kù)在windows程序中通過(guò)LoadLibrary和FreeLibrary反復(fù)加載和卸載后,發(fā)現(xiàn)內(nèi)存和句柄上漲嚴(yán)重,查看動(dòng)態(tài)庫(kù)的dllmain函數(shù),發(fā)現(xiàn)未調(diào)用到ace初始化方法ACE::init(),因此加載動(dòng)態(tài)庫(kù)后,顯式調(diào)用init,卸載前顯式fini,內(nèi)存和句柄果然就沒(méi)有漲了,但出現(xiàn)了一個(gè)新問(wèn)題,在加載到500多次以后,出現(xiàn)了動(dòng)態(tài)庫(kù)文件無(wú)法打開(kāi)錯(cuò)誤,通過(guò)更新ACE最新的6.2.0版本的庫(kù),發(fā)現(xiàn)問(wèn)題依然存在!
前面成功的500多次加載和卸載ace庫(kù),都未看到句柄或者內(nèi)存泄露現(xiàn)象,突然出現(xiàn)不能加載,問(wèn)題開(kāi)始有點(diǎn)難以理解了。
查看ace初始化函數(shù)的實(shí)現(xiàn)代碼,包含了對(duì)對(duì)象管理器單例對(duì)象的初始化操作:
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后不調(diào)用fini,果然到100多次后問(wèn)題就出現(xiàn)了,看來(lái)還是和資源未釋放完全相關(guān)的。在退出函數(shù)fini里注釋代碼,希望能定位到影響問(wèn)題出現(xiàn)概率的那行代碼從而找到相關(guān)的資源信息,把fini函數(shù)如下代碼注釋后,問(wèn)題概率加大:
// Close the main thread's TSS, including its Log_Msg instance.ACE_OS::cleanup_tss (1 /* main thread */);很快可以想到是tss資源泄漏了,通過(guò)在tss資源申請(qǐng)的系統(tǒng)函數(shù)TlsAlloc里增加斷點(diǎn),定位到資源申請(qǐng)的位置: 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()通過(guò)觀察,發(fā)現(xiàn)第二次申請(qǐng)的tss資源在fini函數(shù)調(diào)用后并沒(méi)有釋放掉,導(dǎo)致tss資源出現(xiàn)了泄漏,申請(qǐng)代碼如下: 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!}}}
因此,一個(gè)解決的辦法就是在Cleanup的析構(gòu)函數(shù)中,將in_use_對(duì)應(yīng)的tss資源釋放: ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void) {free_key(in_use_);in_use_ = 0; }
重新編譯ACE庫(kù)后,經(jīng)過(guò)長(zhǎng)時(shí)間測(cè)試問(wèn)題不再出現(xiàn)!
總結(jié)
以上是生活随笔為你收集整理的卸载ACE动态库导致句柄泄漏问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SpringIoC和SpringMVC的
- 下一篇: Xcode各版本官方下载及百度云盘下载,