WinDbg除錯.NET程式入門
俗話說:萬事開頭難!
自從來到新公司遇到效能問題後,需要想辦法解決這個問題,但是一直沒有合適的效能分析工具,然後找到StevenChennet 大神幫忙,他用WinDbg工具遠端幫我分析了一個 dump檔案,但是隻看到鍵盤 “啪啪啪”,得到了結果,卻不是很清楚WinDbg神奇具體如何使用的。結果,第二天,效能問題又來了,總不能每次勞煩大神駕到,所以不得不自己開始學習WinDbg,這裡記錄一個入門過程。
1,首先,下載並安裝WinDbg程式
從下面的地址開啟: https://msdn.microsoft.com/en-us/windows/hardware/hh852365 然後看到 Standalone Debugging Tools for Windows (WinDbg) 下載。 安裝好後,在開始-》Windows Kits資料夾下有 WinDbg(x86),WinDbg(x64) 兩個程式的快捷方式,如果你要除錯 64位的程式,就用WinDbg(x64)。
2,建立記憶體轉儲檔案
可以在工作管理員,程序-》建立轉儲檔案 裡面,得到當前程序的dump檔案,我是用下面這個程式來生成轉儲檔案的: Procdump 下載地址:https://technet.microsoft.com/en-us/sysinternals/dd996900.aspx 有關 ProDump程式的使用,可以參考下面2個部落格文章: High CPU Dump收集工具 - ProcDump使用方法
在命令列,執行這個程式:
procdump -ma mydotNetApp.exe d:myapp.dmp
執行後,將得到一個myapp.dmp 檔案,如果這個檔案是在本機生成的,那麼VS2013可以直接開啟這個檔案並可以分析託管記憶體,但是,往往記憶體轉儲檔案是 在伺服器生成的,而伺服器又很可能跟開發環境不一樣,所以才需要本文介紹的 WinDbg來除錯。
3,配置除錯環境
首先,開啟我們剛才的轉儲檔案,可以使用選單命令開啟: File->Open Crash Dump... 開啟後,會顯示程式當時執行所在的環境,此時,會提示符號檔案沒有發現:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
如果不配置,使用命令的時候會提示錯誤,比如:
0:000> .loadby sos clrjit 0:000> !tp *** ERROR: Symbol file could not be found. Defaulted to export symbols for clr.dll - ************* Symbol Loading Error Summary ************** Module name Error clr PDB not found : e:appserversymbolsdllclr.pdb
e:appserver 是我的dmp檔案所在的目錄,它預設是到symbols 子目錄去找符號檔案去了。
然後,配置下使用此檔案的除錯環境。 在選單命令 File->Symbol path... 開啟對話方塊,選擇瀏覽,找到dmp檔案所在目錄相關的程式檔案目錄 E:AppServer ,該目錄下面有程式相關的 exe,pdb 檔案。
輸入下面的命令:
0:000> .sympath+ c:symbols
Symbol search path is: E:AppServer;c:symbols
Expanded Symbol search path is: e:appserver;c:symbols
Error: Attempts to access 'c:symbols' failed: 0x2 - 系統找不到指定的檔案。
************* Symbol Path validation summary **************
Response Time (ms) Location
OK E:AppServer
Error
這裡不用管,這個資料夾後面可以生成。
0:000> .symfix
0:000> .symfix+ c:symbols
0:000> .sympath
Symbol search path is: srv*
Expanded Symbol search path is: SRV*c:symbols*http://msdl.microsoft.com/download/symbols
************* Symbol Path validation summary **************
Response Time (ms) Location
Deferred
這下對了。 執行下 reload命令:
0:000> .reload
................................................................
................................................................
............
接著執行下面:
0:000> .loadby sos clr
0:000> !tp
The version of SOS does not match the version of CLR you are debugging. Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.296
SOS Version: 4.6.96.0
Failed to load data access DLL, 0x80004005
這裡提示說SOS的版本更CLR不匹配,這裡需要找到當時生成Dump檔案所在的伺服器上的 sos.dll,注意,因為伺服器程式是64位的,所以必須在 .Net Framework64 目錄去找,同時把 mscordacwks.dll 檔案一起拷貝過來(先暫時不用,下面馬上會講到)。
剛才這個命令執行後,我們驚喜的發現,c:symbols 目錄自己建立了,並且下載了 clr.pdb等幾個目錄,這是再將剛才伺服器上拷貝的 sos.dll, mscordacwks.dll ,放到本地機器的 c:symbols 目錄下面。
再次執行這幾個命令:
0:000> .reload
................................................................
................................................................
............
0:000> .loadby sos clr
0:000> !tp
The version of SOS does not match the version of CLR you are debugging. Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.296
SOS Version: 4.6.96.0
Failed to load data access DLL, 0x80004005
還是報錯,看來 sos.dll 沒有載入正確,用下面的命令:
0:000> .load c:symbolssos.dll
0:000> .loadby sos clr
0:000> !tp
這裡load命令必須帶SOS.dll的路徑。載入了它,然後執行 .loadby sos clr ,表示除錯.NET託管程式。
開始漫長的等待,程式視窗提示:
*BUSY* Downloading symbols for [clr.pdb] /
等到相關的符號檔案全部下載完畢,終於出現了久違的成功介面:
CPU utilization: 11%
Worker Thread: Total: 8 Running: 0 Idle: 8 MaxLimit: 32767 MinLimit: 8
Work Request in Queue: 0
--------------------------------------
Number of Timers: 14
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 16 CurrentLimit: 0 MaxLimit: 1000 MinLimit: 8
4,獲取幫助資訊
有關WinDbg詳細的除錯命名,可以參考下面文章: windbg除錯命令 http://www.cnblogs.com/kekec/archive/2012/12/02/2798020.html
或者,你也可以隨時用幫助,檢視如何使用:
0:000> !help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function.
Object Inspection Examining code and stacks
----------------------------- -----------------------------
DumpObj (do) Threads
DumpArray (da) ThreadState
DumpStackObjects (dso) IP2MD
DumpHeap U
DumpVC DumpStack
GCRoot EEStack
ObjSize CLRStack
FinalizeQueue GCInfo
PrintException (pe) EHInfo
TraverseHeap BPMD
COMState
Examining CLR data structures Diagnostic Utilities
----------------------------- -----------------------------
DumpDomain VerifyHeap
EEHeap VerifyObj
Name2EE FindRoots
SyncBlk HeapStat
DumpMT GCWhere
DumpClass ListNearObj (lno)
DumpMD GCHandles
Token2EE GCHandleLeaks
EEVersion FinalizeQueue (fq)
DumpModule FindAppDomain
ThreadPool SaveModule
DumpAssembly ProcInfo
DumpSigElem StopOnException (soe)
DumpRuntimeTypes DumpLog
DumpSig VMMap
RCWCleanupList VMStat
DumpIL MinidumpMode
AnalyzeOOM (ao)
Examining the GC history Other
----------------------------- -----------------------------
HistInit FAQ
HistRoot
HistObj
HistObjFind
HistClear
也可以使用 .help命令,這個不一樣,這裡列出部分命令:
0:000> .help
. commands:
.allow_exec_cmds [0|1] - control execution commands
.allow_image_mapping [0|1] - control on-demand image file mapping
.apply_dbp [<options>] - add current data breakpoint state to a
register context
.asm [<options>] - set disassembly options
.asm- [<options>] - clear disassembly options
.attach <proc> - attach to <proc> at next execution
.block { <commands> } - brackets a set of commands for nested execution
.break - break out of the enclosing loop
也可使用.hh命令: Use ".hh <command>" or open debugger.chm in the debuggers directory to get detailed documentation on a command.
OK,有了dump檔案生成,除錯環境配置,還有幫助命令,現在總算是入門了。