系列目錄 【已更新最新開發文章,點選檢視詳細】
斷點是開發人員的工具箱中最重要的調試技術之一。 若要暫停調試程式執行所需的位置設定斷點。 例如,你可能想要檢視代碼變量的狀态或檢視調用堆棧的某些斷點。
01 在源代碼中設定斷點
可以在任意可執行代碼行上設定斷點。 例如,在以下 C# 代碼,可以設定斷點在變量聲明
for
循環中或内的任何代碼 for
循環。 命名空間或類聲明或方法簽名,無法設定斷點。
若要在源代碼中設定斷點,請單擊代碼行旁邊的最左側邊距中。 您還可以選擇行,然後按F9,選擇調試 > 切換斷點,或右鍵單擊并選擇斷點 > 插入斷點。 斷點顯示為左邊距中的一個紅點。
調試時,執行的斷點處暫停,在執行該行上的代碼之前。 斷點符号顯示黃色箭頭。 當調試器在斷點處停止時,您可以檢視應用程式,包括變量值和調用堆棧的目前狀态。 有關調用堆棧的詳細資訊,請參閱如何:使用調用堆棧視窗。- 斷點是一個觸發器。 您可以單擊它,請按F9,或使用調試 > 切換斷點删除或重新插入。
- 若要禁用斷點而不删除它,将滑鼠懸停或右鍵單擊它,然後選擇禁用斷點。 已禁用的斷點顯示為左邊距中的空點或斷點視窗。 若要重新啟用斷點,請将滑鼠懸停或右鍵單擊它,然後選擇啟用斷點。
- 設定條件和操作、 添加和編輯标簽,或将斷點導出,右鍵單擊該和選擇合适的指令,或将滑鼠懸停其上,然後選擇設定圖示。
02 調用堆棧視窗中設定斷點
若要中斷的指令或調用函數傳回到的行處,可以設定斷點調用堆棧視窗。
在調用堆棧視窗中設定斷點:
- 若要打開調用堆棧視窗中,您必須在調試期間暫停。 選擇調試 > Windows > 調用堆棧,或按Ctrl + Alt+C。
-
在中調用堆棧視窗中,右鍵單擊調用函數,然後選擇斷點 > 插入斷點,或按F9.
調用堆棧的左邊距中的函數調用名稱旁邊會顯示一個斷點符号。
調用堆棧斷點顯示在斷點視窗具有對應于在函數中的下一步可執行指令的記憶體位置的位址。
調試器在指令處中斷。
03 在反彙編視窗中設定斷點
- 若要打開反彙編視窗中,您必須在調試期間暫停。 選擇調試 > Windows > 反彙編,或按Alt + 8。
- 在中反彙編視窗中,單擊想要中斷的指令的左邊距中。 此外可以選擇它,然後按F9,或右鍵單擊并選擇斷點 > 插入斷點。
04 設定函數斷點
當調用函數,可以中斷執行。
若要設定函數斷點:
-
選擇調試 > 新斷點 > 函數斷點,或按Alt +F9 > Ctrl+B。
您還可以選擇建立 > 函數斷點中斷點視窗。
-
在中新函數斷點對話框中,輸入中的函數名稱函數名稱框。
若要縮小範圍的函數規範:
-
使用完全限定的函數名稱。
示例:
Namespace1.ClassX.MethodA()
- 添加重載函數的參數類型。
MethodA(int, string)
- 使用 ! 符号指定子產品。
App1.dll!MethodA
- 在本機中使用上下文運算符C++。
{function, , [module]} [+<line offset from start of method>]
{MethodA, , App1.dll}+2
-
- 在中語言下拉清單中,選擇該函數的語言。
- 選擇 确定。檢視編輯器,所有 Draw() 方法處都以自動插入了斷點。
05 設定資料斷點 (.NET Core 3.0 或更高版本)
為特定對象的屬性發生更改時,資料斷點中斷執行。
若要設定資料斷點
- 在.NET Core 項目中,開始調試,并等待,直到到達一個斷點。
- 在自動,監視,或局部變量視窗中,右鍵單擊一個屬性,然後選擇值更改時中斷的上下文菜單中。
在.NET Core 中的資料斷點不适用于:
- 不是可擴充的工具提示中,局部變量,自動或監視視窗屬性
- 靜态變量
- 使用 DebuggerTypeProxy 特性類
- 在結構内的字段
06 在“斷點”視窗中管理斷點
可以使用斷點視窗來檢視和管理你的解決方案中的所有斷點。 此集中的位置是在大型解決方案中,或對于複雜斷點非常關鍵的調試方案尤其有用。
在斷點視窗中,您可以搜尋、 排序、 篩選、 啟用/禁用或删除斷點。 您還可以設定條件和操作,或添加新的函數或資料斷點。
若要打開斷點視窗中,選擇調試 > Windows > 斷點,或按Alt+F9或Ctrl+Alt+B。
若要選擇要在清單中顯示的列斷點視窗中,選擇顯示列。 選擇一個列标題以對斷點清單,可按該列進行排序。
斷點标簽
可以使用标簽進行排序和篩選清單中的斷點斷點視窗。
1、若要将标簽添加到斷點中,右鍵單擊該斷點的源代碼中或斷點視窗中,并選擇編輯标簽。 添加新标簽或選擇一個現有證書,然後選擇确定。
2、對在斷點清單進行排序斷點通過選擇視窗标簽,條件,或其他列标題。 可以選擇要通過選擇顯示的列顯示列工具欄中。
07 斷點條件
可以通過設定條件來控制在何時何處執行斷點。 條件可以是調試器能夠識别任何有效表達式。 有關有效表達式的詳細資訊,請參見調試器中的表達式。
若要設定斷點條件:
-
右鍵單擊斷點符号,然後選擇條件。 或懸停在斷點符号,選擇設定圖示,并選擇條件中斷點設定視窗。
您還可以在設定條件斷點視窗中的右鍵單擊斷點并選擇設定,然後選擇條件。
- 在下拉清單中,選擇條件表達式,命中計數,或篩選器,并相應地設定值。
- 選擇關閉或按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行的斷點。
代碼走到62行時,斷點變成黃色箭頭,滑鼠懸浮在黃色箭頭上,提示如下,條件表達式計算結果為 true。是以命中62行的斷點。
代碼走到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 斷點操作和跟蹤點
“跟蹤點”是将消息列印到“輸出”視窗的斷點 。 跟蹤點的作用像這種程式設計語言中的一個臨時跟蹤語句。
若要設定跟蹤點:
- 右鍵單擊斷點并選擇操作。 或者,在斷點設定視窗中,懸停在所需斷點,選擇設定圖示,,然後選擇操作。
-
輸入中的消息将消息記錄到輸出視窗字段。 消息可以包含通用文本字元串,值的變量或表達式括在大括号和格式說明符 ( C# 并 C++ ) 的值。
此外可以在消息中使用以下特殊關鍵字:
- $ADDRESS -目前指令
- $CALLER -調用函數名
- $CALLSTACK -調用堆棧
- $FUNCTION -目前函數名
- $PID -程序 id
- $PNAME -程序名稱
- $TID -線程 id
- $TNAME -線程名稱
- $TICK -選中計數 (從 Windows
)GetTickCount
- 若要列印到的消息輸出但不會中斷,選擇視窗繼續執行複選框。 若要列印在跟蹤點的消息和中斷執行,請清除該複選框。
跟蹤點顯示為紅色方塊中的源代碼的左邊距和斷點windows。
按下F5,運作結束後,檢視【輸出】視窗
09 斷點警告
斷點在調試時,有兩個可能的可視狀态: 一個實心的紅色圓和 (白色填充) 空心圓。 如果調試器能夠成功在目标程序中設定斷點,它将保持一個實心的紅色圓。 如果斷點是空心圓,禁用斷點,或嘗試設定斷點時出現警告。 若要确定的不同,斷點上懸停并檢視是否存在一條警告。
以下兩個部分介紹重要警告以及如何解決這些問題。
“尚未為此文檔加載任何符号”
轉到子產品視窗 (調試 > Windows > 子產品) 并檢查是否為你的子產品加載。
- 如果加載你的子產品,則檢查符号狀态列,以檢視是否已加載符号。
- 如果還未加載符号,檢查符号狀态來診斷問題。 從上下文菜單中的子產品上子產品視窗中,單擊符号加載資訊... 若要檢視其中調試器嘗試并加載符号。 有關加載符号的詳細資訊,請參閱指定符号 (.pdb) 和源檔案。
- 如果已加載符号,PDB 不包含有關源檔案的資訊。 以下是幾個可能的原因:
- 如果最近添加的源檔案,确認正在加載的子產品的最新版本。
- 可以建立使用去除的 Pdb /PDBSTRIPPED連結器選項。 去除的 Pdb 不包含源檔案資訊。 确認你正在使用完整 PDB 和不去除的 PDB。
- PDB 檔案部分已損壞。 删除檔案,并執行幹淨的生成的子產品來嘗試解決此問題。
- 如果你的子產品未加載,請檢查以下内容來查找原因:
- 确認您正在調試的正确過程。
- 請檢查你正在調試的代碼正确的類型。 您可以了解哪種代碼将調試器配置為在調試程序視窗 (調試 > Windows > 程序)。 如果想要調試 C# 代碼,例如,确認是否為适當類型的.NET Framework 配置您的調試器 (例如,托管 (v4*) 與托管 (v2*/v3*) 與托管 (CoreCLR))。
"… 目前源代碼是從...中内置的版本不同"
如果源檔案已更改,并且源與正在調試的代碼不再比對,調試器不會設定斷點在代碼中預設情況下。 通常情況下,此問題發生時更改源檔案,但不重新生成的源代碼。 若要解決此問題,重新生成項目。 如果生成系統認為該項目已經是最新但沒有,可以強制項目系統在重新生成通過再次儲存源檔案或通過清除項目的生成輸出生成前。
在極少數情況下,你可能想要調試而無需比對的源代碼。 調試沒有比對的源代碼可以令人混淆的潛在顧客調試體驗,是以請確定這是你想要繼續操作。
若要禁用這些安全檢查,請執行以下操作:
- 若要修改單個斷點,請将滑鼠懸停在編輯器中的斷點圖示,然後單擊設定 (齒輪) 圖示。 檢視視窗添加到在編輯器中。 在檢視視窗頂部,沒有訓示的斷點的位置的超連結。 單擊超連結,以允許修改的斷點位置,然後檢查允許源代碼與原始不同。
- 若要修改此設定對所有斷點,請轉到調試 > 選項和設定。 在 “調試”/“正常” 頁上,清除 “要求源檔案與原始版本完全比對” 選項。 請務必重新啟用此選項,在完成時調試。
10 斷點已成功設定 (無警告),但未命中
本部分提供資訊以對問題進行故障排除時調試器未顯示任何警告 – 斷點是一個實心的紅色圓時主動進行調試,但未命中斷點。
下面是要檢查的幾個事項:
- 如果在多個程序或多台計算機運作你的代碼,請確定你正在調試的正确的程序或計算機。
- 确認你的代碼正在運作。 若要測試你的代碼運作,将調用添加到
(C#/VB) 或System.Diagnostics.Debugger.Break
(C++) 到在您嘗試設定了斷點,然後重新生成你的項目的代碼行。__debugbreak
- 如果你正在調試優化的代碼,請確定在其中設定斷點的函數不被内聯到另一個函數。
如何工作的上一個檢查中所述的測試,測試以及此問題。Debugger.Break
11 删除了斷點,但在再次啟動調試時繼續命中該斷點
如果在調試時删除了斷點,可能在下一步啟動調試的時再次命中該斷點。 要停止命中此斷點,請確定從 “斷點” 視窗删除該斷點的所有執行個體。
·
個人作品
1、BIMFace.Community.SDK.NET
開源位址:https://gitee.com/NAlps/BIMFace.SDK·
2、ZCN.NET.Common
開源位址:https://gitee.com/NAlps/zcn.net.common
技術棧
1、Visual Studio、.C#/.NET、.NET Core、MVC、Web API、RESTful API、gRPC、SignalR、Python
2、jQuery、Vue.js、Bootstrap
3、資料庫:SQLServer、MySQL、PostgreSQL、Oracle、SQLite、Redis、MongoDB、ElasticSearch、TiDB、達夢DM、人大金倉、 神通、南大通用 GBase、華為 GaussDB 、騰訊 TDSQL 、阿裡 PolarDB、螞蟻金服 OceanBase、東軟 OpenBASE、浪潮雲溪資料庫 ZNBase
4、ORM:Dapper、Entity Framework、FreeSql、SqlSugar、分庫分表、讀寫分離
5、架構:領域驅動設計 DDD、ABP
6、環境:跨平台、Windows、Linux(CentOS、麒麟、統信UOS、深度Linux)、maxOS、IIS、Nginx、Apach
7、移動App:Android、IOS、HarmonyOS、微信、小程式、快應用、Xamarin、uni-app、MUI、Flutter、Framework7、Cordova、Ionic、React Native、Taro、NutUI、Smobiler
雲原生、微服務、Docker、CI/CD、DevOps、K8S;
Dapr、RabbitMQ、Kafka、分布式、大資料、高并發、負載均衡、中間件、RPC、ELK;
.NET + Docker + jenkins + Github + Harbor + K8S;·
作者:張傳甯 微軟MCP、系統架構設計師、系統內建項目管理工程師、科技部創新工程師。
專注于微軟.NET技術(.NET Core、Web、MVC、WinForm、WPF)、通用權限管理系統、工作流引擎、自動化項目(代碼)生成器、SOA 、DDD、 雲原生(Docker、微服務、DevOps、CI/CD);PDF、CAD、BIM 審圖等研究與應用。
多次參與電子政務、圖書教育、生産制造等企業級大型項目研發與管理工作。
熟悉中小企業軟體開發過程:需求分析、架構設計、編碼測試、實施部署、項目管理。通過技術與管理幫助中小企業快速化實作網際網路技術全流程解決方案。