1. 程式人生 > >Visual Studio 除錯技巧

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 }

除錯的根本目的是跟蹤程式碼、程式的狀態,判斷是否按照期望的行為執行。常用的跟蹤手段有控制檯輸出、日誌輸出以及斷點除錯。

  1. 控制檯輸出用於開發環境,可以在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