2010-03-26 61 views
3

我有一個外部(.Net)dll,我必須用於應用程序。不幸的是,該DLL有幾個已知的內存泄漏。我們正在努力讓dll的作者修復內存泄漏,但同時我想知道什麼是最好的方式來使用dll而不必處理內存泄漏?如何處理外部DLL中的內存泄漏

回答

3

將.Net程序集移動到它自己的AppDomain中,以便您可以定期卸載模塊可能有助於在泄漏是由於掛在對象引用「太長」,但大部分「內存泄漏」的情況下遇到.Net託管代碼實際上未能釋放非託管資源句柄 - 釋放句柄,關閉文件,關閉網絡連接等。

如果資源由一個負責任的.net託管對象所擁有,該託管對象在IDispose.Close中釋放其非託管句柄(),但是某些骨頭代碼在它應該執行GC循環或卸載程序集的AppDomain時不會調用IDispose.Close,可能會通過「快速」處理擁有的管理對象的最終GC來幫助回收這些孤立的非託管資源。

如果句柄屬於完全不能正確釋放它們的骨頭代碼,卸載程序集的AppDomain不太可能有助於回收孤立的句柄。

當進程終止時,與句柄關聯的大多數Windows資源將被恢復。這有點極端,但如果GC和AppDomain循環不起作用,您可以編寫一個封裝器來討論有問題的.NET程序集類,並使用.NET遠程處理來徹底拋棄程序中的違規程序集。在違規程序集的類和其他應用程序之間進行多少數據交互將決定這是否完全可行。如果違規程序集相當獨立並且有少量的接口入口點,那麼這可能是可行的。在違規組裝過程中,您可以定期關閉它以清除累積的垃圾,而不必關閉自己的過程。

絕對保留絕對最後手段的最後一個想法。嘗試找出哪種內存或資源正在泄漏以及泄露的方式以及AppDomain循環是否會回收丟失的資源。

+0

特別是這個DLL打開一個SqlConnection,並且從不關閉它。 – Dugan 2010-03-26 14:32:52

2

除非被混淆,否則使用.NET Reflector並取出代碼,找到相關部分,修復它,重新編譯它,然後使用重新編譯的代碼。

這可能會或可能不適合您的環境。當我必須弄清楚如何與一些供應商的東西進行交互時,如果他們拒絕我的文檔,我就適用。但請記住,您的業務可能在使用.NET Reflector時遇到問題。

+0

是的,我想我應該提到這不是一個選項,但反射器將是我們如何確定泄漏。由於種種原因,編寫我自己的版本在這裏不起作用。 – Dugan 2010-03-26 01:06:57

+0

甚至沒有「直到供應商交付」解決方法? – jcolebrand 2010-03-26 02:11:50

+0

基本上,問題在於我們在何處部署,生產服務器已經有我們將要使用的組件的一個實例,並且我們無法觸及那個(因爲它在生產中)。這是一個內部問題,可能會在我們到達之前得到解決,但我很好奇在此期間如何處理這個問題。 – Dugan 2010-03-26 02:28:26

1

我們不得不使用第三方庫(用Java開發)服務,並且我們認爲,是這個庫的內存泄漏。我們決定處理這個問題的簡單方法是將服務分成兩個不同的模塊,一個是服務本身,另一個是業務代碼,另一個是可執行文件。所以服務循環,調用另一個可執行文件,它運行在它自己的內存空間中,然後完成它的執行,永遠不會因爲內存泄漏而影響服務應用程序。

所以我的建議是將你的程序從錯誤的DLL中分離出來,或者縮短你使用它的時間,或者改變系統的體系結構,這樣你就不會直接從「長時間運行」應用。

0

如果這是一個嚴重的問題,請將程序集加載到單獨的AppDomain中,並孤立地創建您的躲閃類的實例。它還提供了一個很好的安全邊界。

如果有靜態成員保存在變量上,那麼對於當前的appdomain中的泄漏沒有任何可以做的,因此使用另一個是提供組件隔離的好方法。

將程序集加載到IAppDomain中後,它不能被卸載,但整個AppDomain可以被拆除,GC將收集它。