1. 程式人生 > >Visual Studio - 調試

Visual Studio - 調試

trace 通知 work urn bsp for 系統 程序代碼 iter

異常處理機制

windows預定義了一系列的異常錯誤碼,每種程序異常都有一個對應的錯誤碼,windows系統將這些類似鍵值對關系的數據存儲在異常處理表中(稱為SEH結構化異常處理表)。當CPU執行程序指令時,如果指令出現錯誤,那麽CPU會識別錯誤所對應的錯誤碼,接著執行流程會進入SEH,查找錯誤碼所對應的處理程序,C++、.Net的程序異常都是由RaiseException函數進行處理,異常被處理之後CPU才會繼續執行下一句指令。

異常碼 處理程序
0xC0000005 AccessViolationExceptionHandler( )

0x80000003 LaunchOrNotifyDebugger( )
……

比如打開一個編譯後的程序(如:CUI程序MyApp.exe),當程序出現異常後會被CPU掛起,會進入RaiseException,假如代碼具有try、catch塊,則會把異常交給try、catch處理,如果沒有try、catch塊,那麽異常會交給windows自帶的異常處理塊,該異常處理塊會檢查MyApp.exe的程序代碼是否是由某個調試器運行起來的,如果是,就向調試器發出通知,這樣,調試器就會對異常做出處理,比如visual studio自帶的調試器就是在此時拋出異常信息的,但如果MyApp.exe的程序代碼並不是由某個調試器運行起來的,那麽window就要調用內置的Dr Watson調試器對異常代碼進行"屍檢",也即它會通過一個提示框將錯誤信息拋出。

技術分享圖片

開啟web應用程序的調試

打開web.config,在System.Web配置節將compilation 設為true即可開啟調試

<system.web>
<compilation debug="false" targetFramework="4.6.1" />
</system.web>

當設為false後:

技術分享圖片

斷點調試

普通斷點

光標定位到所在行或直接單擊行左側空白處,會顯示一個紅色圖標表示斷點到此處,程序運行時執行到斷點處就會暫停。

技術分享圖片

斷點後按F5或直接點擊啟動按鈕,當程序執行到斷點處會暫停,此時可以查看變量當前的值。

技術分享圖片

條件

執行到斷點處並不會暫停,直到滿足預設的條件後才會暫停。右擊斷點的紅圖標 - 條件,可以看到與條件有關的三個下拉選項

技術分享圖片

條件表達式:可設置一個當前程序所使用的語言的表達式,比如C#的表達式,表達式為true時就會進入斷點,程序會暫停。

命中次數:使循環體循環到某個特定次數的時候才暫停,可設置==、>=或數倍於,可描述為:當前循環次數==或>=或數倍於

篩選器:指定當執行到哪個線程時才會進入斷點

技術分享圖片

當循環次數>=500時會進入斷點,下圖可以看到c=499時進入中斷模式,因為0-499就是500次。

技術分享圖片

在斷點模式下可以右擊紅色斷點圖標繼續設置斷點條件,達到條件會再次進入斷點。右擊斷點 - 條件,將命中次數設為800

技術分享圖片

按繼續,會發現循環只有在前進到800次時才會進入斷點。

技術分享圖片

操作

下斷點後,右擊斷點,選擇"操作",這種調試方式不會進入中斷模式,但會將指定的變量輸出到輸出窗口,輸入框可填寫由VS提供的變量占位符和你想查看的變量值,當命中斷點後會將輸入框設置的變量當做文本輸出到輸出窗口,變量值應填寫在{}括號中

$FUNCTION將當前斷點所在的函數的名稱作為字符輸出
$CALLER將正在調用當前函數的函數的名稱作為字符輸出
$ADDRESS將正在調用當前函數的指令作為字符輸出
$CALLSTACK將正在執行當前函數的堆棧名稱作為字符輸出
$PID將正在調用當前函數的進程ID作為字符輸出
$PNAME將正在調用當前函數的進程名稱作為字符輸出
$TID將正在調用當前函數的線程ID作為字符輸出
$TNAME將正在調用當前函數的線程名稱作為字符輸出

如:

技術分享圖片

可取消勾選繼續執行,這樣當命中斷點後會中斷代碼的執行,否則不會。輸出結果如下圖:

技術分享圖片

調試快捷鍵

F5:調試的開關(等同於繼續按鈕),按第一次是執行調試,按第二次是結束調試
F9:為光標所在行下斷點
F10:逐過程,即逐條執行,遇到函數時會跳過函數的執行過程直。函數包括了方法、屬性、索引器等。但如果為函數體的任何語句下了斷點,F10還是會進入函數的斷點處。
F11:逐語句,即逐條執行,遇到函數時會進入函數體。

調試類(system.diagnostics)

Debug類和Trace類都提供了靜態方法用於調試,區別僅在於Debug只能在調試版本中有效,而Trace類在調試版本或發布版本中都有效。利用這兩個類,你可以將感興趣的變量輸出到指定的窗口,這些窗口稱為偵聽器窗口。當你使用調試時看見的輸出窗口就是一個默認的偵聽器窗口,而所有的偵聽器窗口都從TraceListener派生。

DefaultTraceListener;
//調試模式下的Visualt studio輸出窗口
TextWriterTraceListener;
//txt窗口,即一個txt文檔
EventLogTraceListener;
//windows事件日誌窗口,即windows的事件日誌文檔
ConsoleTraceListener;
//控制臺窗口
XmlWriterTraceListener;
//xml窗口,即一個xml文檔

例子

//顯示用戶列表
public ActionResult Index()
{
List<UserView> users = new List<UserView>();
foreach (AppUser user in UserManager.Users)
{
users.Add(new UserView { Id = user.Id, Name = user.UserName, Email = user.Email, Password = user.PasswordHash });
}
Debug.Listeners.Add( new TextWriterTraceListener( @"E:\logTest.txt" ) );
Debug.AutoFlush = true;
foreach (var u in users)
{
Debug.WriteLine( $"用戶:{u.Name}" ); //將數據寫入所有的偵聽器窗口
}
Debug.Close( );
return View(users);
}

C# - 學習總目錄

Visual Studio - 調試