63

我有一個正常的私人工作集約80 MB的.NET服務。在最近的負載測試期間,該進程達到了3.5 GB的內存使用量,導致整個機器在物理內存上很低(使用4 GB的3.9 GB),並且在負載測試停止後很久沒有釋放內存。使用任務管理器,我獲取了該進程的轉儲文件並在Visual Studio 2010 SP1中打開了它,並且我可以開始對其進行調試。如何使用轉儲文件來診斷內存泄漏?

如何診斷內存問題?我擁有dotTrace Memory 3.x,它是否支持轉儲文件上的內存分析?如果沒有,Visual Studio 2010 Premium的內存分析功能是否會有幫助(我目前有專業版)? WinDbg可以提供幫助嗎?

UPDATE:的Visual Studio 2013旗艦版現在可以本地使用診斷轉儲文件存儲的問題。有關更多詳細信息,請參閱this blog post

+0

只有Visual Studio 2013 Ultimate Edition ... – Samuel 2013-10-25 12:05:20

+0

@Samuel:真的嗎?多麼悲傷和失望...... – 2013-10-25 22:54:02

+0

這是引用的msdn文章:http://blogs.msdn.com/b/visualstudioalm/archive/2013/06/20/using-visual-studio-2013-to-diagnose-net -memory-issues-in-production.aspx。它表示該選項的先決條件是Ultimate。因爲我認爲它在RC1中可用並且已被推入Ultimate,這是一個相當昂貴的功能,所以令人失望...... – Samuel 2013-10-27 11:06:18

回答

109

安裝WinDbg。您需要確保您獲得正確的版本x86或x64,具體取決於您的轉儲。這是一個用於x86的download的直接鏈接。

在此,你需要確保你採取了正確的轉儲。您可以使用任務管理器來創建轉儲文件(右鍵點擊進程 - >創建轉儲文件)。 如果你使用的是64位,而你的進程是x86,則使用32位版本的任務管理器(C:\ Windows \ SysWOW64 \ taskmgr.exe)來獲取轉儲文件。有關轉儲文件的更多信息,請參見my article,例如,如果您使用的是XP並且需要使用windbg創建轉儲文件。

警告有一個相當陡峭的學習曲線,事情可能無法像這裏所描述的完全一樣,所以回來的任何問題。

我假設您使用.NET4,因爲您可以在Visual Studio中打開轉儲。這裏有一個非常快速指南,以幫助您與您的dmp文件的工作:

1)運行WinDbg中,符號集路(文件 - >符號搜索路徑)來

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols 

2)打開崩潰轉儲或將您的.DMP文件拖到WinDbg上。

3)鍵入此到命令窗口

.loadby sos clr 

(僅供參考,用於.NET 2,命令應該是.loadby sos mscorwks

4)然後鍵入這個

!dumpheap -stat 

其列出了對象的類型和數量。 看起來是這樣的:

enter image description here

您必須分析這個在您的應用程序的情況下,看有無出現異常。

還有更多windbg,谷歌是你的朋友。

+1

這是一個很好的工具,它可以在兩個不同的內存轉儲之間創建一個差異來指示增長:http://thinkexception.blogspot.de/2010/06/tool-to-bompare-two-windbg-dumpheap.html – Samuel 2013-10-25 12:34:56

+5

使用「!dumpheap - 「活 - 活」,以避免看死的物體。 – 2015-10-12 12:53:26

+0

@帕特霍夫曼好皮卡! – wal 2017-01-21 14:42:57

0

http://msdn.microsoft.com/en-us/library/ee817660.aspx

微軟有一個蒞臨指導。但是,對於初學者來說這太難了。

dotTrace可以生成可視化內存圖表(比WinDbg更好),但從不用於轉儲。

+0

非常有趣的指南。那些P&P傢伙肯定會推出好東西。 – 2012-03-01 16:04:51

27

通常,如果您在託管應用程序中存在泄漏,則表示某些內容未被收集。常見的來源包括:

  • 事件處理程序:如果訂戶未被刪除,發佈者將保留它。

  • 終結:一個封閉終結將防止運行的任何其他終結終結器線程,從而防止這些情況下被回收。

  • 類似地,死鎖的線程將保持它所擁有的任何根。當然,如果你有死鎖的線程可能會影響到應用程序的幾個層次。

要解決此問題,您需要檢查託管堆。 WinDbg + SOS(或PSSCOR)會讓你這樣做。 !dumpheap -stat命令列出整個託管堆。

您需要了解堆中預期的每種類型的實例數。一旦發現某些看起來很奇怪的事情,可以使用!dumpheap -mt <METHOD TABLE>命令列出給定類型的所有實例。

下一步是分析這些實例的根。隨機挑選一個,然後做一個!gcroot。這將顯示特定實例的根源。尋找事件處理程序和固定對象(通常表示靜態引用)。如果你在那裏看到終結器隊列,你需要檢查終結器線程正在做什麼。爲此,請使用!threads!clrstack命令。

如果對於該實例一切看起來不錯,則轉到另一個實例。如果這樣做不會產生任何結果,您可能需要返回再次查看堆並從那裏重複。

其他泄漏源包括:未卸載的組件和大對象堆的碎片。 SOS/PSSCOR可以幫助你找到這些,但我現在要跳過細節。

如果你想知道更多我推薦Tess' blog。我還做了一些視頻,介紹如何使用WinDbg + SOS(herehere)。

如果您可以選擇在運行時調試進程,我建議使用PSSCOR而不是SOS。 PSSCOR實質上是SOS資源的一個專用分支,它已經通過附加命令得到了增強,許多現有的SOS命令也得到了改進。例如。 !dumpheap命令的PSSCOR版本有一個非常有用的增量列,這使得更容易排除內存泄漏故障。

爲了使用它,您需要啓動您的進程,附加WinDbg並加載PSSCOR並執行!dumpheap -stat。然後,讓流程再次運行,以便進行分配。中斷執行並重復該命令。現在PSSCOR會顯示自上次檢查後添加/刪除的實例的數量。

+1

Very有用的信息,謝謝! – 2012-03-04 14:28:26

+0

當downvoting時,請發表評論。謝謝。 – 2016-02-17 06:34:37

3

自2017.2版本以來,JetBrains dotMemory支持Windows內存轉儲分析及其所有功能和花哨的GUI。

+0

真的很整潔! – 2017-12-05 19:52:23