Visual Studio 除錯技巧
寫在前面:假定你在日常的工作中使用到了Visual Studio,並期望瞭解一些除錯技巧來提高工作效率,也許本文適合你。以下Visual Studio簡稱vs。
一、入門
以最簡單的控制檯應用程式為例,程式碼如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 int result = Sum(2, 3); 6 Console.WriteLine("2+3={0}", result); 7 } 8 9 private static int Sum(int a,int b) 10 { 11 return a + b; 12 } 13 }
除錯的根本目的是跟蹤程式碼、程式的狀態,判斷是否按照期望的行為執行。常用的跟蹤手段有控制檯輸出、日誌輸出以及斷點除錯。
- 控制檯輸出用於開發環境,可以在vs輸出視窗中檢視程式輸出的內容如下圖所示:
由於是控制檯應用程式,Console.WriteLine() 輸出的內容不會顯示在輸出視窗,故採用Trace.WriteLine() 。對非控制檯應用程式,Console.WriteLine() 輸出的內容會正常顯示在輸出視窗。
2. 日誌輸出用於開發環境和生產環境,但更多用於生產環境,用來收集程式的執行資訊。常用的日誌元件有Log4Net、NLog以及自定義日誌元件。依據問題嚴重程度大致分為嚴重錯誤、錯誤、警告、資訊以及除錯資訊等幾個級別。可結合實際需求靈活配置。
3. 斷點除錯多用於開發環境,通過設定斷點,讓程式在指定的位置暫停,以便觀察上下文環境情況。
以上圖為例,新增斷點後,滑鼠移動到變數名上,可以觀察一些變數的值。對於複雜型別的變數,通過選中變數,右鍵選擇快速監視的方式。避免滑鼠移動後,監視的資訊消失。
以上三種除錯方法中,對於開發環境而言,使用最為頻繁的方法當數斷點除錯。後面以斷點除錯為主,深入介紹。
二、進階
-
啟動外部程式
要使用斷點除錯,需要滿足一些斷點除錯的條件。對於可執行程式,如控制檯應用程式、窗體應用程式、WPF應用程式以及Web應用程式,啟動除錯後,可以在期望的位置新增斷點。而對於如動態庫型別,不可以直接啟動除錯。想要除錯這類專案,有兩種方式。一種是可以設定專案屬性中的啟動操作,指定引用該動態庫的可執行程式路徑。
另一種方式是執行呼叫了動態庫的可執行程式,通過附加可執行程式程序的方式來除錯。
-
附加程序
新建 DllDemo 動態庫專案,新增 MyMath 類,新增靜態方法 Max(int a,int b) 。程式碼如下:
1 using System; 2 3 namespace DllDemo 4 { 5 public class MyMath 6 { 7 public static int Max(int a,int b) 8 { 9 return Math.Max(a, b); 10 } 11 } 12 }
新增對 DllDemo 動態庫專案引用, 並修改控制檯應用程式如下。為了方便後續除錯,控制檯應用程式中新增 Console.Read()。
1 using DllDemo; 2 using System; 3 using System.Diagnostics; 4 5 namespace DebugDemo 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 Console.WriteLine("等待鍵盤輸入..."); 12 13 Console.Read(); 14 15 int result = Sum(2, 3); 16 17 Console.WriteLine(string.Format("2+3={0}", result)); 18 19 result = MyMath.Max(2, 3); 20 21 Console.WriteLine(string.Format("MyMath.Max(2, 3)={0}", result)); 22 } 23 24 private static int Sum(int a, int b) 25 { 26 return a + b; 27 } 28 } 29 }
執行控制檯應用程式DebugDemo.exe ,附加該程序,在合適的位置新增斷點。
-
檢視呼叫堆疊
當程式包含介面繼承、抽象類繼承等邏輯,導致結構過於複雜,知道功能入口以及出口,想要了解過程時,呼叫堆疊會比較有用。以下面程式碼為例:
private static void DoWork() { DoWork1(); } private static void DoWork1() { DoWork2(); } private static void DoWork2() { DoWork3(); } private static void DoWork3() { Console.Write("DoWork3"); }
假設知道功能入口為DoWork,功能結果為DoWork3,想要了解DoWork3的呼叫邏輯,可以在DoWork3中設定斷點,啟動除錯後開啟呼叫堆疊視窗,如下圖:
-
異常設定
當程式執行以後,結果不是預期的。初步猜測發生了異常,由於某些原因,捕獲了異常,卻未妥善處理,導致異常資訊被“吞”掉。此時,異常設定會格外有效。以下面程式碼為例:
private static void TryToDivideByZero() { try { int a = 9; int b = 0; int c = a / b; } catch(Exception ex) { Console.WriteLine(ex.Message); } }
由於方法中存在異常,又有異常捕獲,後續邏輯會被打斷,此時對異常設定做如下設定:
重新除錯程式會有如下結果,方便快速定位異常發生點。
三、高階
在某些場景下,開發環境執行正常,非開發環境執行異常,依賴常規手段無法定位問題原因,想要斷點除錯,非開發環境執行缺少VS時,遠端除錯會比較有效。
在VS安裝目錄下拷貝遠端除錯所需的資料夾x86,x64到非開發環境
依據遠端目標機系統環境,執行x86/x64資料夾下msvsmon.exe,選擇工具中的選項選單做如下配置:
執行待除錯程式後,在VS中選擇除錯>附加到程序(ctrl+alt+p),設定連線型別,連線目標(遠端ip地址或計算機名)後查詢,會自動列出相關內容。
在可用程序中選擇對應的程序
在合適的位置新增斷點即可開始除錯了
&n