WinDBG工具简介(.net大会中张银奎先生介绍)
對于一般的程序不需要使用WinDBG工具去調(diào)試,使用MDBG就OK
使用WinDBG + SOS調(diào)試.Net程序的一般步驟
2009-03-281.?加載進(jìn)程和SOS擴(kuò)展:
???????a. F6或者使用菜單Files –> Attach to a process…來Attach一個(gè)托管進(jìn)程
???????b.使用命令.loadby sos mscorwks來加載SOS擴(kuò)展(注意:.Net1.1時(shí)代的SOS擴(kuò)展已經(jīng)自帶于下載安裝的WinDBG中,從.Net2.0以后,SOS擴(kuò)展已經(jīng)自帶到.Net框架中:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\SOS.dll,為了不至于引起混淆,最好的方法就是使用前面的loadby調(diào)試器元命令來讓WinDBG自己決定加載什么版本的SOS。?mscorwks表示.Net框架的工作站版本,現(xiàn)在我們安裝的.Net Framework都是該版本)
???????c.加載SOS后,使用命令.chain來查看調(diào)試鏈中是否已經(jīng)成功包含SOS擴(kuò)展,如下圖的WinDBG輸出就表示已經(jīng)成功的加載了SOS:
??????
2.?查看進(jìn)程加載的模塊并加載調(diào)試符號:
???????Attach到進(jìn)程并順利加載SOS擴(kuò)展后,我們可以使用lm命令來查看當(dāng)前進(jìn)程已經(jīng)加載的模塊,WinDBG會列出一個(gè)模塊加載列表,這個(gè)列表非常有用,我們后面設(shè)置斷點(diǎn),查看方法表和IL以及匯編代碼都需要使用到相應(yīng)的Module Name。另外對于我們常用的情況:調(diào)試IISHost的進(jìn)程,由于進(jìn)程的名字都是w3wp,我們需要區(qū)分出哪個(gè)進(jìn)程才是我們想要調(diào)試的Application,這個(gè)時(shí)候我們就可以通過lm命令列出的加載模塊列表來判斷:
?
???????接下來我們就可以根據(jù)Module Name來給對應(yīng)的Module加載調(diào)試符號庫,由于在使用WinDBG進(jìn)行調(diào)試的時(shí)候大多數(shù)時(shí)候我們都會查看匯編代碼,所以加載調(diào)試符號對于輔助我們更好的看懂匯編代碼和相關(guān)的變量命名是必須的,WinDBG默認(rèn)會幫我們加載相關(guān)Module的調(diào)試符號,我們也可以使用ld [ModuleName]來顯示的加載某一個(gè)Module的調(diào)試符號,例如ld BasicDebugDemo指定加載BasicDebugDemo這個(gè)Module的調(diào)試符號。
?
3.?準(zhǔn)備就緒,開始調(diào)試:
???????經(jīng)過1,2兩個(gè)步驟的準(zhǔn)備,我們的調(diào)試環(huán)境已經(jīng)準(zhǔn)備好了,接下來就可以開始調(diào)試了,下面介紹一些重要的和常用的調(diào)試命令:
???????1)?根據(jù)調(diào)試符號庫的信息查看類或者方法在.Net執(zhí)行引擎中的具體元信息,包括類的方法表地址,類在運(yùn)行時(shí)的元信息(父類元信息地址,虛方法表地址等很多有用信息),這些信息是我們接下來調(diào)試的基礎(chǔ)!使用命令!name2ee [ModuleName] [ClassName or MehodName]來進(jìn)行查看,例如:!name2ee BasicDebugDemo BasicDebugDemo.Program:
?
???????我們也可以使用!name2ee命令直接查看某個(gè)類方法的元信息:
?
?
2)?有了上面得到的一個(gè)類的方法表的入口地址后,我們就可以使用!dumpmt [-md] [MethodTabel Address]來查看這個(gè)類中每一個(gè)方法的具體運(yùn)行時(shí)信息(加帶md選項(xiàng)表示我們要查詢每一個(gè)方法聲明的入口地址),例如我們利用上面得到的00993030這個(gè)地址,!dumpmt –md 00993030:
?
3)?另外我們通過上面的!name2ee命令除了拿到MehodTable的地址外,還拿到了Program這個(gè)Class的運(yùn)行時(shí)元信息地址EEClass Address,所以我們可以通過!dumpclass [Class Address]來查看這個(gè)類中的具體內(nèi)容(比如其中的靜態(tài)變量的地址等):
4)?上面提到了一個(gè)很重要的信息MehodDesc,得到這個(gè)MethodDesc有什么用呢?首先我們可以使用!dumpil [MethodDesc]來查看其編譯后的IL代碼:
5)?另外如果這個(gè)方法已經(jīng)被JIT了,那么我們調(diào)用!dumpmd [MethodDesc]會得到下面的信息:
???????接下來我們就可以使用!u [LocalCodeAddr]來查看生成的本地匯編代碼:
?
6)?上面能獲取的元信息我們基本上都獲取了,有了這些元信息(主要是代碼地址信息)我們要下斷點(diǎn)就很簡單了,我們有很多種方式來給我們的代碼的指定位置加上斷點(diǎn)P
????a.首先如果調(diào)試符號加載成功的話,我們可以直接使用很直觀的原始方法命名來給指定的方法入口處加上斷點(diǎn):!bpmd [ModuleName] [MethodName],例如!bpmd BasicDebugDemo BasicDebugDemo.Program.CreateFooObject
????b.如果我們有MethodDesc,也可以直接使用!bpmd -md [MethodDesc]來給方法入口處加上斷點(diǎn),例如!bpmd -md 0099301c
???c.我們上面看到了本地匯編代碼,所以我們也可以使用bp [CodeAddr]來給某個(gè)方法內(nèi)部的某行代碼加上斷點(diǎn)。
???d.我們可以使用bl命令來列出所有已加載的斷點(diǎn),也可以使用bc [BreakPoint ID]命令來刪除指定ID的斷點(diǎn)(用bl命令列出的斷點(diǎn)列表種有各個(gè)斷點(diǎn)的ID),或者使用bc *來刪除所有的斷點(diǎn)。
????e.斷點(diǎn)加載成功后,WinDBG會給出類似下面這樣的提示:
?????????Found 1 methods...
MethodDesc = 00993028
Adding pending breakpoints...
????f.當(dāng)我們的斷點(diǎn)命中后,我們?nèi)匀豢梢韵衿胀ㄕ{(diào)試一樣來使用F10 Step Out單步執(zhí)行,使用F11來Step Into單步執(zhí)行。注意:這里的單步執(zhí)行,都是指單步匯編代碼,而不是我們所寫的代碼。
7)?在命中斷點(diǎn)后我們就可以通過查看類命令來查看棧和堆中的變量的值以及當(dāng)前的調(diào)用堆棧:
??a.使用!clrstack可以查看當(dāng)前的條用堆棧,使用!clrstack –l可以查看當(dāng)前調(diào)用堆棧以及其上的局部變量和值,使用!clrstack –p可以查看當(dāng)前調(diào)用堆棧上的參數(shù)變量以及值,使用!clrstack –a可以查看當(dāng)前堆棧上所有局部變量和參數(shù)變量以及值(格式為StackAddress =??StackValue)。!clrstack命令只會顯示托管代碼的調(diào)用堆棧,如果想查看完整的調(diào)用堆棧可以使用!dumpstack命令:
b.使用!dso命令可以查看堆棧上的所有對象
??c.使用!do [ObjectAddress]查看指定對象的具體內(nèi)容:
?
8)?除了通過堆棧查看棧上的變量外,我們還可以直接通過!dumpheap來查看目前堆中的所有對象,但是由于一般情況下堆中存在的變量會非常的多(包含.Net框架里的很多預(yù)定義對象),所以直接使用!dumpheap得到的結(jié)果一般我們很難查看。大多數(shù)情況下,我們需要查看的是堆中指定類型的對象,所以我們可以使用!dumpheap –type [ClassName]來查看指定類型的對象:
9)如何檢查內(nèi)存泄漏?WinDBG SOS中有一個(gè)很有用的命令!GCRoot [ObjectAddress]可以幫助我們查看指定對象的引用情況,這個(gè)信息可以很好的幫助我們分析那些本應(yīng)該沒有引用但卻一直還存在有效引用的對象,由此發(fā)現(xiàn)我們代碼中潛在的內(nèi)存泄漏,同時(shí)我們也可以觀察到哪些對象是目前沒有引用了,但是GC還沒有回收的:
?
4.?總結(jié):
1) WinDBG不是專門用于調(diào)試.Net程序的工具,它更偏向于底層,可用于內(nèi)核和驅(qū)動調(diào)試。進(jìn)行普通的.Net程序調(diào)試還是使用微軟專為.Net開發(fā)的調(diào)試工具MDBG更方便一些。但是WinDBG能看到更多的底層信息,對于某些特別疑難的問題調(diào)試有所幫助,例如內(nèi)存泄漏等問題。
2) SOS擴(kuò)展命令中最有用的命令是!help命令J,使用該命令可以列出所有可用的SOS擴(kuò)展命令列表,使用!help [SOSCommandName]可以查看每一個(gè)具體擴(kuò)展命名的詳細(xì)使用說明,例如!help dumpheap就可以查看!dumpheap這個(gè)擴(kuò)展命名的具體使用方法。多多利用!help命名可以很快上手SOS。
3) WinDBG本身的資料可以參考?張銀奎?先生的《軟件調(diào)試》一書,另外在互聯(lián)網(wǎng)上也有非常多的WinDBG資料。
轉(zhuǎn)載于:https://www.cnblogs.com/mashuping/archive/2009/03/28/1424187.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的WinDBG工具简介(.net大会中张银奎先生介绍)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rs.Open SQL,Conn,adO
- 下一篇: SQLSERVER2005安装说明