Visual Studio 調試系列3 斷點


斷點是開發人員的工具箱中最重要的調試技術之一。 若要暫停調試程序執行所需的位置設置斷點。 例如,你可能想要查看代碼變量的狀態或查看調用堆棧的某些斷點。

01 在源代碼中設置斷點

可以在任意可執行代碼行上設置斷點。 例如,在以下 C# 代碼,可以設置斷點在變量聲明for循環中或內的任何代碼for循環。 命名空間或類聲明或方法簽名,無法設置斷點。

若要在源代碼中設置斷點,請單擊代碼行旁邊的最左側邊距中。 您還可以選擇行,然后按F9,選擇調試 > 切換斷點,或右鍵單擊並選擇斷點 > 插入斷點。 斷點顯示為左邊距中的一個紅點。

調試時,執行的斷點處暫停,在執行該行上的代碼之前。 斷點符號顯示黃色箭頭。

當調試器在斷點處停止時,您可以查看應用程序,包括變量值和調用堆棧的當前狀態。 有關調用堆棧的詳細信息,請參閱如何:使用調用堆棧窗口

  • 斷點是一個觸發器。 您可以單擊它,請按F9,或使用調試 > 切換斷點刪除或重新插入。

  • 若要禁用斷點而不刪除它,將鼠標懸停或右鍵單擊它,然后選擇禁用斷點。 已禁用的斷點顯示為左邊距中的空點或斷點窗口。 若要重新啟用斷點,請將鼠標懸停或右鍵單擊它,然后選擇啟用斷點。

  • 設置條件和操作、 添加和編輯標簽,或將斷點導出,右鍵單擊該和選擇合適的命令,或將鼠標懸停其上,然后選擇設置圖標。

02 調用堆棧窗口中設置斷點

若要中斷的指令或調用函數返回到的行處,可以設置斷點調用堆棧窗口。

在調用堆棧窗口中設置斷點:

  1. 若要打開調用堆棧窗口中,您必須在調試期間暫停。 選擇調試 > Windows > 調用堆棧,或按Ctrl + Alt+C。

  2. 在中調用堆棧窗口中,右鍵單擊調用函數,然后選擇斷點 > 插入斷點,或按F9.

    調用堆棧的左邊距中的函數調用名稱旁邊會顯示一個斷點符號。

調用堆棧斷點顯示在斷點窗口具有對應於在函數中的下一步可執行指令的內存位置的地址。

調試器在指令處中斷。

03 在反匯編窗口中設置斷點
  1. 若要打開反匯編窗口中,您必須在調試期間暫停。 選擇調試 > Windows > 反匯編,或按Alt + 8。

  2. 在中反匯編窗口中,單擊想要中斷的指令的左邊距中。 此外可以選擇它,然后按F9,或右鍵單擊並選擇斷點 > 插入斷點。

04 設置函數斷點

當調用函數,可以中斷執行。

若要設置函數斷點:

  1. 選擇調試 > 新斷點 > 函數斷點,或按Alt +F9 > Ctrl+B。

    您還可以選擇新建 > 函數斷點中斷點窗口。

  2. 在中新函數斷點對話框中,輸入中的函數名稱函數名稱框。

    若要縮小范圍的函數規范:

    • 使用完全限定的函數名稱。

      示例:Namespace1.ClassX.MethodA()

    • 添加重載函數的參數類型。

      示例:MethodA(int, string)

    • 使用 ! 符號指定模塊。

      示例:App1.dll!MethodA

    • 在本機中使用上下文運算符C++。

      {function, , [module]} [+<line offset from start of method>]

      示例:{MethodA, , App1.dll}+2

  3. 在中語言下拉列表中,選擇該函數的語言。

  4. 選擇 確定。查看編輯器,所有 Draw() 方法處都以自動插入了斷點。

05 設置數據斷點 (.NET Core 3.0 或更高版本)

為特定對象的屬性發生更改時,數據斷點中斷執行。

若要設置數據斷點

  1. 在.NET Core 項目中,開始調試,並等待,直到到達一個斷點。

  2. 在自動,監視,或局部變量窗口中,右鍵單擊一個屬性,然后選擇值更改時中斷的上下文菜單中。

    管理數據斷點

在.NET Core 中的數據斷點不適用於:

  • 不是可擴展的工具提示中,局部變量,自動或監視窗口屬性
  • 靜態變量
  • 使用 DebuggerTypeProxy 特性類
  • 在結構內的字段

 

06 在“斷點”窗口中管理斷點

可以使用斷點窗口來查看和管理你的解決方案中的所有斷點。 此集中的位置是在大型解決方案中,或對於復雜斷點非常關鍵的調試方案尤其有用。

在斷點窗口中,您可以搜索、 排序、 篩選、 啟用/禁用或刪除斷點。 您還可以設置條件和操作,或添加新的函數或數據斷點。

若要打開斷點窗口中,選擇調試 > Windows > 斷點,或按Alt+F9或Ctrl+Alt+B。

 若要選擇要在列表中顯示的列斷點窗口中,選擇顯示列。 選擇一個列標題以對斷點列表,可按該列進行排序。

斷點標簽

可以使用標簽進行排序和篩選列表中的斷點斷點窗口。

1、若要將標簽添加到斷點中,右鍵單擊該斷點的源代碼中或斷點窗口中,並選擇編輯標簽。 添加新標簽或選擇一個現有證書,然后選擇確定。

2、對在斷點列表進行排序斷點通過選擇窗口標簽,條件,或其他列標題。 可以選擇要通過選擇顯示的列顯示列工具欄中。

07 斷點條件

可以通過設置條件來控制在何時何處執行斷點。 條件可以是調試器能夠識別任何有效表達式。 有關有效表達式的詳細信息,請參見調試器中的表達式

若要設置斷點條件:

  1. 右鍵單擊斷點符號,然后選擇條件。 或懸停在斷點符號,選擇設置圖標,並選擇條件中斷點設置窗口。

    您還可以在設置條件斷點窗口中的右鍵單擊斷點並選擇設置,然后選擇條件。

  1. 在下拉列表中,選擇條件表達式,命中計數,或篩選器,並相應地設置值。

  2. 選擇關閉或按Ctrl+Enter關閉斷點設置窗口。 或者,從斷點窗口中,選擇確定關閉對話框。

 

條件表達式

當選擇條件表達式,可以選擇兩個條件:為 true或發生更改時。 選擇如此時,滿足表達式時中斷或發生更改時表達式的值已更改時中斷。

1、示例1,設置條件表達式為 true, index == 1

按下F5,啟動調試,由於第一次 index 等於0,所以37行斷點沒有命中,直接走到43行的正常斷點處。

第一次循環結束后,index的值增加了1,等於1。進入到第二次循環時,按下F5,由於 index = 1,滿足設置的表達式,所以命中了37行的斷點。

第二次循環結束后,index的值增加了1,等於2。進入到第三次循環時,按下F5,由於 index = 2,不滿足設置的表達式,所以沒有命中37行的斷點,直接走到43行的正常斷點處。

2、示例2:設置條件表達式為 更改時, index 

按下F5,啟動調試,由於第一次 index 等於0,第一次進入循環,結束前 index的值未改變仍然為0,沒有改變,所以37行斷點沒有命中,直接走到43行的正常斷點處。

第一次循環結束后,index的值增加了1,等於1。進入到第二次循環時,按下F5,由於 index = 1,值更改了,滿足設置的條件,所以命中了37行的斷點。

第二次循環結束后,index的值增加了1,等於2。進入到第三次循環時,按下F5,由於 index = 2,值更改了,滿足設置的條件,所以命中了37行的斷點。

 如果使用無效語法設置斷點條件,則會顯示警告消息。 如果在指定斷點條件時使用的語法有效但語義無效,則在第一次命中斷點將出現警告消息。 在任一情況下,調試器將中斷時它會命中斷點無效。 僅在條件有效且計算結果為 false時才會跳過斷點。

不同編程語言的“更改時”字段的行為不同 :

對於本機代碼,調試器不會考慮更改,因此不會命中第一次計算斷點條件的第一次計算。

對於托管代碼,調試器命中斷點后第一次計算發生更改時處於選中狀態。

在條件表達式中使用對象 Id (C#和F#僅)

有些的時候,當你想要觀察特定對象的行為。 例如,你可能想要找出為什么對象插入到集合一次以上。 在 C# 和 F# 中,可以創建引用類型的特定實例的對象 ID,並在斷點條件下使用它們。 對象 ID 由公共語言運行時 (CLR) 調試服務生成並與該對象關聯。

創建對象 ID

1、設置斷點在代碼中的某個位置后創建對象。

2、開始調試,並在斷點處暫停執行,選擇調試 > Windows > 局部變量Alt+ 4以打開局部變量窗口。

      查找特定對象實例在局部變量窗口中,右鍵單擊它,然后選擇創建對象 ID

      應該會在“局部變量” $ 窗口中看到, 窗口中設置斷點來中斷調用函數返回到的指令或行處的執行。 這就是對象 ID。

展開名稱,看到 $1 與 tri 對象完全相同

以同樣的方式給 rec、cir、shapes 對象分別創建對象ID,分別對應 $2  $3  $4 

3、在該對象添加到集合處, 右鍵單擊該斷點並選擇“條件” 。

4、在“條件表達式”字段中使用對象 ID 。 例如,如果變量item是要添加到集合中,選擇的對象為 true並鍵入item == $<n > ,其中<n > 的對象 ID 號.

     會在將該對象添加到集合中時中斷執行。

tri 對象添加到集合處,設置條件為 tri == $1

rec 對象添加到集合處,設置條件為 rec == $2

 cir 對象添加到集合處,設置條件為 rec == $3

按下F5繼續運行,

代碼走到61行時,斷點變成黃色箭頭,鼠標懸浮在黃色箭頭上,提示如下,條件表達式計算結果為 true。所以命中61行的斷點。

按下F5繼續運行,

代碼走到62行時,斷點變成黃色箭頭,鼠標懸浮在黃色箭頭上,提示如下,條件表達式計算結果為 true。所以命中62行的斷點。

按下F5繼續運行,

代碼走到63行時,斷點變成黃色箭頭,鼠標懸浮在黃色箭頭上,提示如下,條件表達式計算結果為 true。所以命中63行的斷點。

 

 

如果將61行的條件設置為 tri == $2。根據上述的生成的對象ID,該表達式返回false。

再次F5,運行到61行時,提示報錯。因為 tri 是 Triangle 類的對象,$2 是 Rectangle 類的對象創建的ID,所以無法進行 == 運算符的比較。調試器報錯。

但是按下F5,仍然可以繼續運行。

 

如果把61行的條件表達式修改為 tri.Equals($2),再次調試時,由於該表達式返回false,所以沒有命中61行的斷點。直接跳到62行。

 

     若要刪除對象 ID,請右鍵單擊中的變量局部變量窗口,然后選擇刪除對象 ID。

對象 ID 創建弱引用,且不會阻止對象被垃圾回收。 它們僅對當前調試會話有效。

命中次數

如果你懷疑你的代碼中的循環開始產生錯誤行為在一定數量的迭代后,可以設置一個斷點以停止執行的命中數,而無需重復按該數后F5來訪問該迭代。

下列條件中斷點設置窗口中,選擇命中計數,然后指定迭代數。 在以下示例中,斷點設置為其他每次迭代命中:

 F5調試,第一次 i = 0,不是 testInt 的2倍整數,所以沒有命中74行的斷點,直接跳到76行。

當 testInt的值為 2、4、16、22、46時,都能命中74行的斷點。

 

篩選器

可以將斷點限制為僅在指定設備上或在指定進程和線程中觸發。

下條件中斷點設置窗口中,選擇篩選器,然后輸入一個或多個以下表達式:

  • MachineName = "name"
  • ProcessId = value
  • ProcessName = "name"
  • ThreadId = value
  • ThreadName = "name"

將字符串值放在雙引號內。 可以使用 & (AND)、 || (OR)、 ! (NOT) 和括號合並子句。

提醒:斷點條件 模式下進行調試,不能按F10,只能按F5進行調試才能看到實際效果。

08 斷點操作和跟蹤點

“跟蹤點”是將消息打印到“輸出”窗口的斷點 。 跟蹤點的作用像這種編程語言中的一個臨時跟蹤語句。

若要設置跟蹤點:

  1. 右鍵單擊斷點並選擇操作。 或者,在斷點設置窗口中,懸停在所需斷點,選擇設置圖標,,然后選擇操作。

  2. 輸入中的消息將消息記錄到輸出窗口字段。 消息可以包含通用文本字符串,值的變量或表達式括在大括號和格式說明符 ( C#  C++ ) 的值。

    此外可以在消息中使用以下特殊關鍵字:

    • $ADDRESS -當前指令
    • $CALLER -調用函數名
    • $CALLSTACK -調用堆棧
    • $FUNCTION -當前函數名
    • $PID -進程 id
    • $PNAME -進程名稱
    • $TID -線程 id
    • $TNAME -線程名稱
    • $TICK -選中計數 (從 Windows GetTickCount)
  3. 若要打印到的消息輸出但不會中斷,選擇窗口繼續執行復選框。 若要打印在跟蹤點的消息和中斷執行,請清除該復選框。

跟蹤點顯示為紅色方塊中的源代碼的左邊距和斷點windows。

按下F5,運行結束后,查看【輸出】窗口

09 斷點警告

斷點在調試時,有兩個可能的可視狀態: 一個實心的紅色圓和 (白色填充) 空心圓。 如果調試器能夠成功在目標進程中設置斷點,它將保持一個實心的紅色圓。 如果斷點是空心圓,禁用斷點,或嘗試設置斷點時出現警告。 若要確定的不同,斷點上懸停並查看是否存在一條警告。

以下兩個部分介紹重要警告以及如何解決這些問題。

“尚未為此文檔加載任何符號”

轉到模塊窗口 (調試 > Windows > 模塊) 並檢查是否為你的模塊加載。

 

  • 如果加載你的模塊,則檢查符號狀態列,以查看是否已加載符號。

    • 如果還未加載符號,檢查符號狀態來診斷問題。 從上下文菜單中的模塊上模塊窗口中,單擊符號加載信息... 若要查看其中調試器嘗試並加載符號。 有關加載符號的詳細信息,請參閱指定符號 (.pdb) 和源文件
    • 如果已加載符號,PDB 不包含有關源文件的信息。 以下是幾個可能的原因:
      • 如果最近添加的源文件,確認正在加載的模塊的最新版本。
      • 可以創建使用去除的 Pdb /PDBSTRIPPED鏈接器選項。 去除的 Pdb 不包含源文件信息。 確認你正在使用完整 PDB 和不去除的 PDB。
      • PDB 文件部分已損壞。 刪除文件,並執行干凈的生成的模塊來嘗試解決此問題。
  • 如果你的模塊未加載,請檢查以下內容來查找原因:

    • 確認您正在調試的正確過程。
    • 請檢查你正在調試的代碼正確的類型。 您可以了解哪種代碼將調試器配置為在調試進程窗口 (調試 > Windows > 進程)。 如果想要調試 C# 代碼,例如,確認是否為適當類型的.NET Framework 配置您的調試器 (例如,托管 (v4*) 與托管 (v2*/v3*) 與托管 (CoreCLR))。

 

"… 當前源代碼是從...中內置的版本不同"

如果源文件已更改,並且源與正在調試的代碼不再匹配,調試器不會設置斷點在代碼中默認情況下。 通常情況下,此問題發生時更改源文件,但不重新生成的源代碼。 若要解決此問題,重新生成項目。 如果生成系統認為該項目已經是最新但沒有,可以強制項目系統在重新生成通過再次保存源文件或通過清除項目的生成輸出生成前。

在極少數情況下,你可能想要調試而無需匹配的源代碼。 調試沒有匹配的源代碼可以令人混淆的潛在顧客調試體驗,因此請確保這是你想要繼續操作。

若要禁用這些安全檢查,請執行以下操作:

  • 若要修改單個斷點,請將鼠標懸停在編輯器中的斷點圖標,然后單擊設置 (齒輪) 圖標。 查看窗口添加到在編輯器中。 在查看窗口頂部,沒有指示的斷點的位置的超鏈接。 單擊超鏈接,以允許修改的斷點位置,然后檢查允許源代碼與原始不同。
  • 若要修改此設置對所有斷點,請轉到調試 > 選項和設置。 在 “調試”/“常規” 頁上,清除 “要求源文件與原始版本完全匹配” 選項。 請務必重新啟用此選項,在完成時調試。

 

10 斷點已成功設置 (無警告),但未命中

本部分提供信息以對問題進行故障排除時調試器未顯示任何警告 – 斷點是一個實心的紅色圓時主動進行調試,但未命中斷點。

下面是要檢查的幾個事項:

  1. 如果在多個進程或多台計算機運行你的代碼,請確保你正在調試的正確的進程或計算機。
  2. 確認你的代碼正在運行。 若要測試你的代碼運行,將調用添加到System.Diagnostics.Debugger.Break(C#/VB) 或__debugbreak(C++) 到在您嘗試設置了斷點,然后重新生成你的項目的代碼行。
  3. 如果你正在調試優化的代碼,請確保在其中設置斷點的函數不被內聯到另一個函數。Debugger.Break如何工作的上一個檢查中所述的測試,測試以及此問題。

 

11 刪除了斷點,但在再次啟動調試時繼續命中該斷點
如果在調試時刪除了斷點,可能在下一步啟動調試的時再次命中該斷點。 要停止命中此斷點,請確保從 “斷點” 窗口刪除該斷點的所有實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM