12個Visual Studio除錯效率技巧

芝麻麻雀發表於2020-07-07

在這篇文章中,我們假定讀者瞭解VS基本的除錯知識,如:

  • F5 開始使用偵錯程式執行程式
  • F9 在當前行設定斷點
  • F10 執行到下一個斷點處
  • F5 從被除錯的已停止程式恢復執行
  • F11 步進到函式內(如果當前程式指標指向一個函式)
  • F10 步過函式(如果當前程式指標指向一個函式)
  • Shift+F11 步出執行的函式
  • 暫停執行
  • 附加到程式
  • 滑鼠懸停時快速檢視原始碼中的元素
  • 除錯視窗:區域性變數、監視、即時視窗、模組、呼叫堆疊、異常設定

許多開發人員使用這個功能強大的工具包來處理除錯會話。然而,Visual Studio除錯工具提供了更多的功能。下面是一系列Visual Studio除錯效率技巧。注意,這些提示和快捷方式已經在的Visual studio 2019 16.6 EN-US版本中進行了驗證,驗證時Visual studio沒有安裝擴充套件。

1、執行到游標位置

使用快捷鍵Ctrl+F10,您可以讓偵錯程式執行到游標所在行位置。

執行到游標位置

2、通過點選滑鼠,執行到當前位置

在除錯執行的程式時,通過滑鼠懸停在當前行的程式碼上時,出現綠色的符號,可以點選此符號,直接讓斷點執行到此處。
通過點選滑鼠,執行到當前位置

3、在此處作為下一條要執行的語句

在除錯執行的程式時,通過滑鼠懸停在當前行的程式碼上時,通過按住Ctrl鍵轉換為將此處作為下一條要執行的語句。它與通過綠色箭頭符號執行到這裡不同,此功能將會跳過中間的語句,直接將斷點跳轉到此處。因此,在下面的動圖中,我們可以在監視視窗中引用obj仍然為null,中間的MyClass建構函式並沒有被執行。
在此處作為下一條要執行的語句

4、資料斷點:當值發生變化時,觸發中斷(值更改時中斷)

當你設定一個非靜態的設定器為斷點時,當所有物件的屬性的值發生更改時觸發斷點。通過區域性視窗(監視器視窗)右鍵點選:值更改時中斷選單,單個物件也可以獲得相同的行為。

下面的動畫說明了這個功能,只有當obj2.Prop發生變化時,命中斷點,而obj1.Prop發生變化時沒有命中斷點。

注意:資料斷點繫結到活動物件時,旨在除錯期間起作用。因此,一旦除錯過程停止,設定的斷點就會丟失,在以後的除錯過程中不能重用它。

資料斷點:值更改時中斷

5、條件斷點

可以將條件附加到斷點中,以便盡在特定場景中觸發中斷。在下面的動圖中,我們在迴圈中定義條件i>6的斷點。然後點選繼續,可以看到一旦斷點停止,i的值實際上變成了7

6、跟蹤斷點

在遇到斷點時,停止程式執行時最常見的操作。但是,你可以選擇在輸出視窗中不終止(或帶終止)列印一些跟蹤資訊。下面的動圖說明了這種可能性。我們在輸出視窗中跟蹤i從0到9的值。注意:跟蹤斷點在編輯器的斷點顯示位置顯示為菱形形狀。

注意,條件和跟蹤操作都可以在斷點上指定。
跟蹤斷點

7、跟蹤超出作用域的物件

在監視視窗中,通過當前執行範文內引用的名稱來跟蹤物件。但是,當這樣的跟蹤引用超出作用域時,即使在引用物件仍處於活動狀態時,它在監視視窗的上下文也不安的毫無意義並且被禁用。

在許多情況下,我們想繼續跟蹤作用域外物件的狀態。為此,請在監視視窗中右鍵單擊此類引用,單擊選單[Make Object ID] 建立物件ID(M),並要在監視器中新增$1(或者$2,$3,...,取決於你已經建立了多個物件ID)。

下面的動圖演示瞭如何跟蹤作用域外物件的屬性獲取器的狀態,該屬性獲取器以字串的形式返回實際的日期時間。它很好地顯示了當引用objFct()上下文中超出作用域時,要觀看的obj項將被禁用,而$1仍然會獲得更新。
跟蹤超出作用域的物件

8、檢視函式返回的值

函式返回的值有時在原始碼中被忽略,或者有時這個值在除錯時無法被顯示的訪問。

這樣的返回值可以顯示在除錯->視窗->自動視窗中。偽變數$ReturnValue也可以在即時視窗和監視視窗中使用,以方便檢視最後一個函式呼叫的返回值。

注意,選單除錯->視窗->自動視窗僅在Visual Studio偵錯程式附加到程式並且程式被偵錯程式暫停時可用。

檢視函式返回的值

9、重新附加到程式

Visual Studio 2017開始,重新附加到程式Shift+Alt+P工具被提出,並且非常方便。將偵錯程式附加到某個程式後,Visual Studio會記住它,並建議將偵錯程式重新附加到同一程式。斜體也一樣,因為這裡有一個關於程式標識的啟發式方法:

  • 如果已附加的程式仍然執行著,重新附加到程式,重新附加到它。
  • 否則,Visual Studio將嘗試查詢和前一個程式名具有相同名稱的單程式,並將偵錯程式重新附加到該程式。
  • 如果找到幾個使用此名稱的程式,則開啟“附加到程式”對話方塊,只顯示名稱相同的程式
  • 如果找不到具有此名稱的程式,則顯示“附加到程式”對話方塊

重新附加到程式

重新附加到程式也適用於涉及多個程式的除錯會話。在這種情況下,Visual Studio會嘗試使用上述相同的啟發式方法來查詢它附加到的所有程式。

10、在即時視窗和在觀察視窗的No-Side-Effect評估

有時,在即時視窗或監視視窗中評估表示式時,某些狀態會更改。這種行為通常時不希望發生的。你不想僅僅因為需要評估表示式的值而破壞除錯程式的狀態。這種情況被稱為Heisenbug,該術語時物理學家Werner Heisenberg的雙關語,它首先斷言了量子力學的觀察者效應,該現象指出,觀察系統的行為不可避免的會改變器狀態。

為了避免更改任何狀態,你可以在表示式後面加上nse(No-Side-Effect)。下面的動圖說明了這種可能性(在監視視窗中監視State的值是否有變化)。

在即時視窗和在觀察視窗的評估

下面這種動圖是nse在監視視窗的使用。由於SideEffectFct()所觀察的項中有Refresh評估按鈕,所以此示例比前一個示例更簡單。

11、在原始碼中顯示執行緒

除錯多執行緒應用程式是有名的複雜。希望在原始碼中顯示執行緒按鈕能提供很大的幫助。它在編輯器的左側邊欄引入標記圖示,以跟蹤其他執行緒被暫停的位置。這個標記可以用來顯示執行緒ID,並最終切換到另一個執行緒。注意:如果至少兩個執行緒在同一位置暫停,則會顯示不同的標記符號。
在原始碼中顯示執行緒

更多除錯多執行緒應用程式的技巧可以在這個微軟文件中找到:Get started debugging multithreaded applications (C#, Visual Basic, C++)

https://docs.microsoft.com/en-us/visualstudio/debugger/get-started-debugging-multithreaded-apps?view=vs-2019

下面是這個演示的原始碼,如果你想演示它,可以進行參考:

using System;
using System.Threading;
 
class Program {
   static void Main() {
      for (int i=0; i< 5; i++) {
         // Avoid capturing a loop variable in the lambda below
         int j = i;
         // So 2 thread are blocked on '0' case
         if (j == 1) { j = 0; } 
         ThreadPool.QueueUserWorkItem(delegate { Method(j); });
      }
      Thread.Sleep(60000);
   }
   static void Method(int id) {
      switch(id) {
         case 0:
            Thread.Sleep(60000); break;
         case 1:
            Thread.Sleep(60000); break;
         case 2:
            Thread.Sleep(60000); break;
         case 3:
            Thread.Sleep(60000); break;
         case 4:
            Thread.Sleep(60000); break;
      }
   }
}

12、從反編譯的IL程式碼中除錯原始碼

我們經常依賴一些黑盒元件:我們沒有原始碼的元件。

但是,在除錯複雜行為時,觀察甚至除錯引用的黑盒元件引用的邏輯。這就是為什麼從16.5版本開始,Visual Studio 2019可以從編譯好的程式中生成一些原始碼。這樣的原始碼是可以除錯的。這個特性是基於開源軟體(OSS)工程:ILSpy(https://github.com/icsharpcode/ILSpy)。

反編譯選單可以在模組視窗的元件右鍵選單(如下面的動圖所示)和Source Not FoundNo Symbols Loaded對話方塊中給出。

IL程式碼反編譯為原始碼不可能是完美的,因為一些原始碼資訊在編譯時丟失了。因此,這個特性有一些限制,在這個官方文件的最後會解釋:Generate source code from .NET assemblies while debugging

https://docs.microsoft.com/en-us/visualstudio/debugger/decompilation?view=vs-2019

從反編譯的IL程式碼中除錯原始碼

結尾

Visual Studio非常出色,在除錯方面尤其出色。 在這裡,我試圖選擇一些既隱藏又經常有用的技巧,希望它們能幫助您提高生產率。

如果你感覺有用,請關注一下我的公眾號

相關文章