天天看點

使用Windbg調試.Net應用程式

 1. 解決線上.NET應用程式的如下問題:

  • 崩潰
  • CPU高
  • 程式異常
  • 程式Hang死

2. 安裝WinDbg:

http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx

3. 配置WinDbg:

運作WinDbg->菜單->File->Symbol File Path->按照下面的方法設定_NT_SYMBOL_PATH變量:

在彈出的框中輸入“C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols”(按照這樣設定,WinDbg将先從本地檔案夾C:\MyCodesSymbols中查找Symbol,如果找不到,則自動從MS的Symbol Server上下載下傳Symbols)。另一種做法是從這個Symbol下載下傳位址中http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx,下載下傳相應作業系統所需要的完整的Symbol安裝包,并進行安裝,

4. 利用WinDbg裡的adplus來擷取dump檔案。

 Dump檔案是程序的記憶體鏡像。可以把程式的執行狀态通過調試器儲存到dump檔案中。

在WinDbg安裝目錄裡可以找到adplus.exe,把他拖入到指令行中,然後用指令

adplus.exe -hang -pn test.exe -o c:\dumps  // 抓取目前的dump檔案

adplus.exe -crash -pn test.exe -o c:\dumps  // 監聽應用程式,當crash時,擷取dump檔案

指令-pn :應用程式名,-p:應用程式pid,-odump檔案輸出路徑

5. 利用WinDbg加載dump檔案加載調試器

運作WinDbg->菜單->File->Open Cresh dump 打開dump檔案,并加載.net調試器

使用Windbg調試.Net應用程式

.loadby sos mscorwks  .Net 3.5版本及以下

.loadby sos clr  .Net 4.0

如果伺服器的.Net版本與本機不比對需要伺服器版本的mscordacwks.dll檔案

并設定.sympath = mscordacwks_x86_x86_2.0.50727.3607.dl

6. WinDbg的基本指令

help  sos指令幫助

!threads  顯示所有線程

!dumpheap  顯示托管堆的資訊

!clrstack  顯示調用棧

!dumpobj  顯示一個對象的内容

!dumparray  顯示數組

!syncblk  顯示同步塊

!runaway  顯示線程cpu時間

!gcroot  跟蹤對象記憶體引用

!pe  列印異常

7. WinDbg的使用

當我在Form中執行這段代碼:

public Form1(){
			InitializeComponent();
			AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
		}
	private void UnhandledExceptionProc(object obj){
			try {
				throw new Exception("1st chance");
			} catch (Exception) {
				MessageBox.Show("after 1st");
			}
			int d = 0;
			int n = 1 / d;
}
           

并活動dump檔案

使用Windbg調試.Net應用程式

用windbg打開dump檔案後輸入-pe:可以看到問題的所在。

使用Windbg調試.Net應用程式

異常如此重要,是以作業系統提供了對應的調試功能,可以使用調試器來檢視異常。異常發生後,作業系統在調用使用者态程式的異常處理函數前,會檢查目前使用者态程式是否有調試器加載。如果有,那麼作業系統會首先把異常資訊發送給調試器,讓調試器有觀察異常的第一次機會,是以也叫做first chance exception,調試器處理完畢後,作業系統才讓使用者态程式來處理。 如果使用者态程式處理了這個異常,就沒調試器什麼事了。否則,程式在unhandled exception崩潰前,作業系統會給調試器第二次觀察異常的機會,是以也叫做second chance exception。

《Windows使用者态程式高效排錯》

分析以下代碼:可以看出DummyObject 會占用很多記憶體,甚至導緻記憶體溢出

private void MemeryLeakProc(object obj)
		{
			while (true) {
				for (int i = 0; i < 100 * 1024; i++) {
					DummyObject o = new DummyObject();
					list.Add(o);
				}
				Thread.Sleep(1000);
			}
		}
           

windbg指令:!dumpheap –stat 統計堆棧記憶體

使用Windbg調試.Net應用程式

線程Hang住的常見原因

-線程池或工作線程集中在某個耗時的工作當中,或者被其他線程鎖住

核心問題,找到被hang住的線程

!threads

~*e!clrstack

!synblk

lock (syncRoot) {
				int tp;
				int io;
				//ThreadPool.GetMaxThreads(out tp, out io);
				for (int i = 0; i < 100; i++) {
					Thread hangThread = new Thread(HangProc);
					hangThread.Start();
				}
				MessageBox.Show("Press to release lock");
			}
           
  private void HangProc(object obj)
  {
   lock (syncRoot) {
    n = 0;
   }
  }
           
使用Windbg調試.Net應用程式
使用Windbg調試.Net應用程式

CPU高

-如果與業務量沒有提升,有線程在長時間的處理

核心問題,找到占用CPU的線程

!runaway

~*e!clrstack

線程死鎖出現的情況:

兩個鎖A,B,

一個線程已經拿到鎖A,申請鎖B,

另一個線程已經拿到鎖B,申請鎖A

核心問題:找到鎖定的線程

!threads

!syncblk

~*e!clrstack

•兩條指令可以解決大部分的問題 •!dumpheap –stat •~*e!clrstack