我正在調試這個數據庫項目。它爲更高級別的應用程序提供對SQLite的訪問。它被設計爲異步運行,也就是說,它有像ExecuteRequestAsync()和IsRequestReady()這樣的方法。當調用ExecuteRequestAsync時,它會派生一個boost :: thread來執行該作業並立即返回該函數。當高層應用程序決定不再需要運行請求的結果時,它可能會調用DumpRequest()來取消它。由於很難正常取消數據庫請求,DumpRequest的實現只是維護一個「清理監視器線程」,等待「已完成的請求」並將其刪除。所有boost ::線程通過升壓:: shared_ptr的管理,如:boost :: thread導致小事件句柄泄漏?
boost::shared_ptr<boost::thread> my_thread = new boost::thread(boost::bind(&DBCon::RunRequest, &this_dbcon));
而且當它不再需要(被取消):
vector<boost::shared_ptr<boost::thread> > threads_tobe_removed;
// some iteration
threads_tobe_removed[i].get()->join();
threads_tobe_removed.erase(threads_tobe_removed.begin()+i);
我創造了這個單元測試項目來測試執行和轉儲請求的機制。它運行請求並隨機取消正在運行的請求,並重複數千遍。機制證明是可以的。一切按預期工作。
但是,通過通過sysinternal的Process Explorer觀察單元測試項目,發現存在句柄泄漏問題。每經過500次,手柄數量增加1,永不退回。這是增加的「事件」類型句柄。文件和線程句柄沒有增加(當然,隨着線程的產生,句柄的數量也在增加,但每隔一百次就會有一次Sleep(10000)調用,以等待它們被清理,以便可以觀察到句柄計數)。
我一直沒有管理自己的事件處理。它們是在創建線程時由boost :: thread創建的。我只保證優雅地關閉線程,我不知道事件是用來幹什麼的。
我想知道是否有人遇到過類似的問題?什麼可能是這個泄漏的原因? Process Explorer中的這個數字是否可靠足以將其稱爲句柄泄漏?有什麼方法可以追蹤和修復它嗎?
我在Windows Vista上使用Visual C++靜態鏈接boost 1.40。
產生100個請求並立即轉儲它們通常在Intel CoreDuo E6600上花費約3秒鐘。打開的句柄的峯值數量約爲300(包括事件,線程,文件等)。當測試進入睡眠狀態時,打開的手柄編號逐漸降低到65左右。每隔500小時通過一次,將導致「結束」編號從65增加到66,然後是67. 這實際上是一次每50,000次執行。這非常奇怪和令人沮喪。 – 2009-11-16 12:20:22
「打開的句柄數逐漸減少」,因爲清理監視器線程正在收集它們。 – 2009-11-16 12:23:40