.NET调试学习
診斷工具
動手實現一個適用于.NET Core 的診斷工具
Dump
dump在計算機科學中是一個廣泛運用的動詞、名詞。
作為動詞:一般指將數據導出、轉存成文件或靜態(tài)形式。比如可以理解成:把內存某一時刻的內容,dump(轉存,導出,保存)成文件。
作為名詞:一般特指上述過程中所得到的文件或者靜態(tài)形式。
1、為什么要dump(dump的目的)?
因為程序在計算機中運行時,在內存、CPU、I/O等設備上的數據都是動態(tài)的(或者說是易失的),也就是說數據使用完或者發(fā)生異常就會丟掉。如果我想得到某些時刻的數據(有可能是調試程序Bug或者收集某些信息),就要把他轉儲(dump)為靜態(tài)(如文件)的形式。否則,這些數據你永遠都拿不到。
2、dump轉儲的是什么內容(dump的對象)?
其實上邊已經提到了,就是將動態(tài)(易失)的數據,保存為靜態(tài)的數據(持久數據)。像程序這種本來就保存在存儲介質(如硬盤)中的數據,也就沒有必要dump。
常出現dump的場景:Unix/Linux中的coredump,Java中的headdump和threaddump。
.NET程序崩潰了怎么抓 Dump ? 我總結了三種方案
WinDbg調式
1、理論學習
.NET高級調試系列-Windbg調試入門篇
WinDbg:Windows 調試工具(WinDbg、KD、CDB、NTSD)
win10上安裝后目錄:C:Program Files (x86)Windows Kits10Debuggersx64
Windbg是Microsoft公司免費調試器調試集合中的GUI的調試器,支持Source和Assembly兩種模式的調試。Windbg不僅可以調試應用程序,還可以進行Kernel Debug。結合Microsoft的Symbol Server,可以獲取系統(tǒng)符號文件,便于應用程序和內核的調試。Windbg支持的平臺包括X86、IA64、AMD64。雖然windbg也提供圖形界面操作,但它最強大的地方還是有著強大的調試命令,一般情況會結合GUI和命令行進行操作,常用的視圖有:局部變量、全局變量、調用棧、線程、命令、寄存器、白板等。其中“命令”視圖是默認打開的。
Windbg在用戶態(tài)和內核態(tài)下,都支持兩種調試模式,即“實時調試模式(Living)”和“事后調試模式(Postmortem)”。
所謂實時模式,是被調試的目標對象(Target)當前正在運行當中,調試器可以實時分析、修改被調試目標的狀態(tài),如寄存器、內存、變量,調試exe可執(zhí)行程序或雙機實時調試都屬于這種模式;
所謂事后模式,是被調試的目標對象(Target)已經結束了,現在只是事后對它保留的快照進行分析,這個快照稱為轉儲文件(Dump文件)。
Windbg另一個重大優(yōu)點,還在于它支持源碼級的調試,就像VC自帶的調試器一樣。雖然提供了用戶界面,但Windbg歸根結底還是需要用戶一個個地輸入命令來指揮其行動。這就是他的Command窗口。每個調試命令都各有使用范圍,有些命令只能用于內核調試,有些命令只能用于用戶調試,有些命令只能用于活動調試。但用戶也不必記得這許多,一旦在某個環(huán)境下,使用了不被支持的命令,都會顯示“No export XXX found”的字樣。
官網:WinDbg 入門(用戶模式)
其他參考:
WinDbg的安裝、配置和功能(系列博文)使用WinDbg調試入門(用戶模式)
一步一個坑 - WinDbg調試.NET程序
Windbg命令相關
WinDbg 命令三部曲:(一)WinDbg 命令手冊
WinDbg 命令三部曲:(二)WinDbg SOS 擴展命令手冊
!DumpHeap 將遍歷 GC 堆對對象進行分析。通過指定不同的選項,可以查看特定的類型、數組和鎖。
!GCRoot [-nostacks] <Object address> 查詢一個對象的所有引用根。
!syncblk看看有沒有 lock 的情況
!DumpStack Objects 顯示當前調用棧上的所有托管對象的信息,可配合 k 或 CLRStack 命令使用
!clrstack 看調用棧
!eeheap -gc命令,看下托管堆大小【即遍歷進程內存中的 CLR 數據結構】
!eeheap -loader命令,看下loader 堆大小(非托管)
WinDbg 命令三部曲:(三)WinDbg SOSEX 擴展命令手冊
用sosex擴展的!dlk命令可以自動檢索是否有死鎖
2、概念原理之:什么是SOS、mscordacwks
參考:windbg分析dump-解決mscorwks不匹配
mscorwks:通用語言運行時 (CLR) 是執(zhí)行托管代碼的 Microsoft .NET 框架的核心引擎。mscorwks.dll是CLR 2.0實現的主要文件。此引擎在本機代碼中實現。
SOS:SOS.DLL可以提供關于CLR的信息,幫助我們在vs和windbg調試托管程序。例如,可以顯示有關托管堆的信息、查找堆損壞情況、顯示運行時使用的內部數據類型以及查看有關運行時內運行的所有托管代碼的信息。
mscorwks使用本機代碼實現了CLR,SOS可以提供托管的CLR信息,而mscordacwks即為連接本機代碼和托管代碼之間的橋。SOS無需了解CLR底層細節(jié)。
官網:SOS.dll (SOS debugging extension)
3、Windbg話題
Windbg From 一線碼農聊技術
幾個分析思路:
內存泄漏:首先就要排查到底是托管堆還是非托管堆的問題 ,參考:記一次 .NET 某HIS系統(tǒng)后端服務 內存泄漏分析
實踐
如何在 .NET 程序萬種死法中有效的生成 Dump
如何在 .NET 程序萬種死法中有效的生成 Dump
用Windbg打開生成的Dump文件【用vs也可以打開dmp文件進行分析】
執(zhí)行命令如下:
!address -summary 查看當前 process 的內存占用量
!dumpheap -stat -min 1024 尋找大對象(單位Byte),在托管堆中
!dumpheap-typeSystem.String-min10240 用-type屬性篩選出>10k的字符串。
!gcroot4a855060 【參數是 MT對應的任意一個address】
如何在 NET 程序萬種死法中有效的生成 Dump (下)
以下是一些說明:
ProcDump生成Dump文件
ProcDump使用
procdumpConsoleApp2-m1024-maE:
et5ConsoleApp1ConsoleApp2inDebug
如果你的機器有多個 ConsoleApp2,可以將其替換成 pid(進程id)
報錯error opening
是需要使用管理員命令提示符才能成功抓取dump
官網
ProDump是跨平臺的命令行工具,可以在指定的條件下生成dump文件。
應用場景:主要用于高CPU占用率的性能分析優(yōu)化,程序停止響應的調試,First chance異常捕獲等,還可以監(jiān)視內存使用、結合系統(tǒng)性能計數器使用。
常用用法:
在命令提示符下procdump -?可以查看全部參數的說明,這里列舉幾個常用的:
-c/-cl: 監(jiān)視CPU占用率閥值,-c為當CPU占用率高于該值時創(chuàng)建dump,-cl則在低于該值時創(chuàng)建dump。
-u: 監(jiān)視單核心的CPU占用率,與-c一起使用
-s: 時間,以秒為單位,結合-c使用實現當連續(xù)N秒CPU占用高于某值時保存dump。
-n: 設置數量,保存多個dump后才退出該程序。
-h: 當進程中存在掛起窗口(不響應窗口消息)時創(chuàng)建dump。
-m:內存到達多大(MB)時創(chuàng)建dump。
-e:當進程遇到未處理的異常時寫入dump【程序奔潰退出】。-e 1 表示在第一次異常時創(chuàng)建dump。eg:托管程序無法捕獲非托管C/c++的異常
-w:如果指定的進程沒有運行,請等待它啟動。
-ma:使用所有進程內存 寫入dump。默認轉儲格式僅包含線程和句柄信息。
最后一個參數寫 dmp文件的保存路徑
!dumpheap -stat
【!dumpheap參數和SOS幫助系統(tǒng)的一些一般信息】
報錯1:no export dumpheap found
則執(zhí)行.load sos 繼續(xù)報錯:系統(tǒng)找不到指定的文件
參考:加載擴展DLL:load 需要跟完整路徑:0:000> .load C:WindowsMicrosoft.NETFramework64v4.0.30319SOS.dll
繼續(xù)執(zhí)行 !dumpheap -stat
報錯2:Failed to find runtime DLL (clr.dll),0x80004005
再加載一個其他版本的sos:C:WindowsMicrosoft.NETFramework64v2.0.50727SOS.dll
繼續(xù)報錯:Failed to find runtime DLL (mscorwks.dll),0x80004005
改為加載.netcore 2.1 的sos 【因為.netcore3.1下沒有sos,這就為后續(xù)調試.netcore3.1的程序時埋了個坑】:.load C:Program FilesdotnetsharedMicrosoft.NETCore.App2.1.28sos
參考:.net core dump分析
!gcroot -all報錯:The version of SOS does not match the version of CLR you are debugging
步驟:!dumpheap-typeSystem.String-min10240
正確輸出了,單擊最下面一個。結果顯示 crl版本 與SOS版本不匹配。。所以要下載一個netcore版本下面的SOS。
可是.nercore3.1里面沒有sos.dll,只有一個rm
打開可以看到,進到Installing SOS on Windows
然后執(zhí)行 .load C:Usershuy.dotnetsossos 就好了。
注意:2和3 綜合起來,下次分析dump時,分別執(zhí)行:
.loadby sos crl
.load C:Usershuy.dotnetsossos
!gcroot 返回 Found 0 unique roots
參考:WinDbg not telling me where my string is rooted
這是因為,WinDbg告訴您的是正確的-這些沒有根,它們是垃圾,但是因為它們在LOH上,它們可能不會很快被清除(如果有的話)。您肯定需要重新考慮如何處理XML,將數據流輸入/輸出,而不是預先在內存中加載/創(chuàng)建數據。
修改代碼為:
public static void TestMemory()
{
List<string> list = new List<string>();
for (int i = 0; i < int.MaxValue; i++)
{
string temp = string.Join(",", Enumerable.Range(0, 10000));
list.Add(temp);
if (i % 30 == 0)
SY.Filer.FileHelper.AppendAllText(temp, "temp.txt");
}
Console.ReadLine();
}
重新生成dump去分析
總結
- 上一篇: 三菱a系列motion软体_三菱M70A
- 下一篇: 沈炜:vivo的黄金时代不在过去 仍在将