用Windbg來分析.Net程式的dump
阿新 • • 發佈:2021-09-24
轉自:用Windbg來分析.Net程式的dump - 張三~~ - 部落格園 (cnblogs.com)
介紹
1. 什麼是Windbg
- WinDbg是微軟釋出的一款相當優秀的原始碼級(source-level)除錯工具,可以用於Kernel模式除錯和使用者模式除錯,還可以除錯Dump檔案。
- WinDbg是微軟很重要的診斷除錯工具: 可以檢視原始碼、設定斷點、檢視變數, 檢視呼叫堆疊及記憶體情況。
- Dump檔案是程序的記憶體映象, 可以把程式的執行狀態通過偵錯程式儲存到dump檔案中
2. Windbg可以解決以下問題
◆ 記憶體高
◆ CPU高
◆ 程式異常
◆ 程式Hang死
3. 使用windbg進行除錯分析的兩種方式
- 使用windbg偵錯程式attach到需要除錯的程序。(會暫停程序的執行)
- 抓取程序的dump檔案,使用windbg分析dump
一.準備
1.下載
官網地址:
https://developer.microsoft.com/zh-cn/windows/hardware/windows-driver-kit
選擇對應的工具包下載
2.安裝
- 下載之後點選安裝,可選擇安裝的工具,我們只選擇windbg就可以。安裝之後在debuggers資料夾下選擇32位或64位程式執行
- 開啟windbg之後,需要設定symbol path,可以按快捷鍵Ctrl+S
srvc:\symcachehttp://msdl.microsoft.com/download/symbols;c:\symcache;
3.抓取dump
1. 通過procdump獲取
下載地址:https://technet.microsoft.com/en-us/sysinternals/dd996900
下載之後為壓縮包,將檔案解壓。通過dos命令來生成dump檔案。下面為一條語句為示例
procdump -ma -c 0 -s 3 -n 2 sqlservr.exe -o E:\dumps\
這條語句的意思為:當sqkservr.exe
- -ma 生成full dump, 即包括程序的所有記憶體. 預設的dump格式包括執行緒和控制代碼資訊.
- -c 在CPU使用率到達這個閥值的時候, 生成dump檔案.
- -s CPU閥值必須持續多少秒才抓取dump檔案.
- -n 在該工具退出之前要抓取多少個dump檔案.
- -o dump檔案儲存目錄.
- Sqlservr.exe可替換為程序的ID
下圖為執行示例(sqlserver等操作需要cmd以管理員許可權開啟)
2. 工作管理員抓取
可在工作管理員程序右鍵程序,點選建立轉儲檔案,系統會自動抓取和儲存,儲存完成會彈出對話方塊提示儲存路徑
二.解析
1.解析dump檔案
通過windbg的選單,File—>Open Crash Dump選擇dump檔案開啟。開啟成功介面如下圖所示:
2.命令
1.基本命令
- ?獲取命令提示
- D檢視記憶體資訊
- K觀察棧
- ~顯示和控制執行緒 ~number s number為執行緒id 如:~1s為獲取1號執行緒的上下文
- Q退出
- !runaway檢視執行緒佔用cpu時間,可看出哪個執行緒佔用時間最高(所有執行緒)
- .dump /ma E:/dumps/myapp.dmp抓取dump
2.元命令
- .help獲取命令提示
- .cls清屏
- .ttime檢視執行緒佔用cpu時間,可看出哪個執行緒佔用時間最高(當前執行緒)
3..擴充套件命令
- . chain獲取命令集列表。在已經載入的動態連結庫中。
- .load/.unload載入/解除安裝命令模組
- **!模組名.help **檢視某個擴充套件庫中包含的擴充套件命令
4..Net程式相關命令
基本
- !peb或!dlls列出程序已經載入的dll
- **!threadpool ** 檢視當前CPU狀況 執行緒數等等
- !dumpheap –stat統計堆資訊
- !Threads所有託管執行緒 -special Crl建立的執行緒
- !clrstack看看這個執行緒再幹嘛 執行那些方法
- !clrstack –p addraddr:具體方法的引數值地址
- !do 地址檢視引數值
- !analyze –v顯示分析的詳細資訊
- .reload /i /f強制重新載入pdb
記憶體除錯
- **!eeheap –gc ** 獲取gc中記憶體資訊
- !eeheap –loaderLoader 堆資訊
- !dumpheap –stat統計GC堆的資訊,統計GC堆上存活的物件
- !dumpheap -mt <>檢視該地址上的物件
- !gcroot <<物件地址>>檢視物件根
- **!dumpheap -type <<System.String >> ** 檢視string型別在堆中的資訊
- !helproot-檢視gcroot的幫助
在解析.Net程式時首先要載入執行環境framework版本對應的SOS.DLL:
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.DLL
這裡只是寫一些比較常用的命令,想要詳細瞭解更多命令了以到官網檢視
3.高記憶體佔用示例
【讀取檔案程式碼】
【在程式碼執行過程中抓取dump檔案開啟,並載入sos.dll】
【執行!dumpheap –stat獲取最高記憶體佔用的地址】
【!gcroot address獲取呼叫函式】
最終,我們找到了高記憶體的呼叫入口!
當然如果gc堆上的佔用記憶體較高的物件是自定義的類,那麼就可以直接檢視相關的呼叫函式來分析可能的問題了