1. 程式人生 > 其它 >用Windbg來分析.Net程式的dump

用Windbg來分析.Net程式的dump

轉自:用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.安裝

  1. 下載之後點選安裝,可選擇安裝的工具,我們只選擇windbg就可以。安裝之後在debuggers資料夾下選擇32位或64位程式執行
  1. 開啟windbg之後,需要設定symbol path,可以按快捷鍵Ctrl+S
    。把下面的路徑貼上進去儲存。系統進行dump解析等操作的時候會自動下載需要的符號表
    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

這個程序執行時間cpu的佔用超過0%,時間超過3秒,則在E:\dumps下生成一個dump檔案。一直到生成2個為止。下面為命令介紹

  • -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堆上的佔用記憶體較高的物件是自定義的類,那麼就可以直接檢視相關的呼叫函式來分析可能的問題了