使用正確的斷點類型
本文說明如何在Visual Studio中使用不同類型的斷點來改善偵錯效率。 它涵蓋可套用斷點的各種案例,例如暫停程式代碼執行、記錄資訊,以及追蹤變數狀態中的變更。 本文說明如何設定條件斷點、追蹤點、數據斷點、相依斷點和暫存斷點。 它也包含設定函式斷點的詳細指示。 本指南對於希望利用斷點在 Visual Studio 中有效偵錯的開發人員而言至關重要。
如果您不熟悉在 Visual Studio 中使用斷點,請參閱 先了解斷點的使用,然後再閱讀本文。
如需此檔的最佳體驗,請從文章頂端的清單選擇您慣用的開發語言或運行時間。
場景
下表顯示斷點的常見偵錯案例,以及案例的建議斷點類型。
場景 | 描述 |
---|---|
如何暫停執行中的程式代碼,以檢查可能包含 Bug 的程式代碼行? | 設定斷點。 如需詳細資訊,請參閱 斷點使用入門。 |
我的變數是否有非預期的值? 或者,我想要在應用程式達到特定狀態時檢查看看吗? | 請嘗試條件斷點,透過條件邏輯來控制斷點的啟用位置和時機。 右鍵點擊斷點以新增條件。 當變數等於非預期的值時,將條件設定為 true。 如需詳細資訊,請參閱 斷點條件。 |
如何在可設定的條件下將資訊記錄到 [輸出] 視窗,而不需修改或停止我的程序代碼? | 追蹤點可讓您在不修改或停止程式代碼的情況下,在可設定的條件下將信息記錄至 [輸出] 視窗。 如需詳細資訊,請參閱 在 Visual Studio 調試程式中使用追蹤點。 |
如何知道變數的值何時變更? | 針對 C++,請設定 資料斷點。 針對使用 .NET Core 3 和更新版本的應用程式,您也可以設定數據斷點 。 否則,針對 C# 和 F#,您只能 使用條件斷點來追蹤物件識別碼,。 |
當另一個斷點觸發時,我該如何中斷執行? | 設定相依斷點,只有在另一個斷點先觸發時,才會中斷執行。 如需詳細資訊,請參閱 相依斷點。 |
我可以只觸發斷點一次嗎? | 設定暫時斷點,讓您只中斷程式代碼一次。 如需詳細資訊,請參閱 暫存斷點。 |
是否可以在某次迭代時暫停迴圈中的程式碼? | 設定相依斷點,僅在首先觸發另一個斷點時才會中斷執行。 如需詳細資訊,請參閱 點擊計數。 |
當我知道函式名稱但不是函式位置時,是否可以在函式開頭暫停程序代碼? | 您可以使用函式斷點來執行此動作。 如需詳細資訊,請參閱 設定函式中斷點。 |
我可以在多個具有相同名稱的函式開頭暫停程序代碼嗎? | 當您有多個具有相同名稱的函式(如多載函式或位於不同專案中的函式),您可以使用 函式斷點。 |
斷點動作和追蹤點
追蹤點 是一個斷點,會將訊息列印至 輸出 視窗。 追蹤點可以像程式設計語言中的暫存追蹤語句一樣,而且不會暫停程式碼的執行。 您可以在 [斷點設定] 視窗中設定特殊動作,以建立追蹤點。 如需詳細指示,請參閱 在 Visual Studio 調試程式中使用追蹤點。
斷點條件
您可以藉由設定條件來控制斷點的執行時機與位置。 條件可以是調試程式可辨識的任何有效表達式。 (如需有效表達式的詳細資訊,請參閱調試程式中 表示式。)
若要設定斷點條件:
按滑鼠右鍵按一下斷點符號,然後選取 [條件] (或按 Alt + F9,C)。 或將滑鼠停留在斷點符號上,選取 [設定] 圖示,然後在 [斷點設定] 視窗中選取 [條件]。
您也可以在程式代碼行旁的左邊界中按下滑鼠右鍵,然後從操作功能表中選取 [插入條件式斷點],以設定新的條件式斷點。
您也可以在 [斷點] 視窗中設定條件,方法是以滑鼠右鍵按兩下斷點,然後選取 [設定],然後選取 [條件]
在下拉式清單中,選取 條件表達式、叫用計數,或 篩選,並據以設定值。
選取 [關閉 或按 ctrl+Ctrl 以關閉 [斷點設定] 視窗。 或者,從 [斷點] 視窗中,按下 [確定] 以關閉對話框。
設定條件的斷點會在原始程式碼中以 + 符號顯示,斷點 視窗。
建立條件表達式
當您選取 [條件表達式]時,可以選擇兩個條件:為 true 或 變更時。 選擇 當表達式滿足且為 true 時中斷,或 當表達式的值改變時中斷。
在下列範例中,當 testInt
的值是 4時,才會觸發斷點:
在下列範例中,只有在 testInt
的值變更時,才會觸發斷點:
如果您使用無效的語法設定斷點條件,就會顯示警告訊息。 如果您指定具有有效語法但語意無效的斷點條件,當斷點首次被擊中時會出現警告訊息。 在任一情況下,偵錯工具會在遇到無效的斷點時中斷。 只有在條件有效且評估為 false
時,才會略過斷點。
注意
針對 [當變更] 欄位時,調試程式不會將條件的第一次評估視為變更,因此不會在第一次評估時觸發斷點。
在條件表示式中使用物件識別碼 (僅限 C# 和 F#)
有時候您想要觀察特定對象的行為。 例如,您可能想要找出對象為何多次插入集合中。 在 C# 和 F# 中,您可以為 參考型別的特定實例建立物件識別碼,並在斷點條件中使用它們。 對象標識碼是由 Common Language Runtime (CLR) 偵錯服務所產生,並與 對象相關聯。
若要建立對象標識碼:
在建立 對象之後,於程式代碼中設定斷點。
開始偵錯,並在執行暫停於斷點時,選取 [偵錯]>Windows>[局部變數](或按 Ctrl + Alt + V,L)以開啟 [局部變數] 視窗。
在 [局部變數] 視窗中尋找特定物件實例,以滑鼠右鍵按兩下它,然後選取 [[建立物件標識符]。
您應該會在 局部 視窗中看到 $ 加上一個數字。 這是物件識別碼。
在您想要調查的點新增一個斷點,例如當物件要被加入集合時。 以滑鼠右鍵點擊斷點,然後選取 [條件]。
使用 [條件表達式] 字段中的對象標識碼。 例如,如果變數
item
是要新增至集合的物件,請選取 [Is true,然後輸入 item == $<n>,其中 <n> 是對象標識符。當該物件要加入至集合時,執行將會中斷。
若要刪除物件識別碼,請在 [局部變數] 視窗中以滑鼠右鍵按變數,然後選取 [刪除物件識別碼]。
注意
物件標識符會創建弱參考,並且不會阻止物件被垃圾回收處理。 它們僅適用於目前的偵錯會話。
設定點擊計數條件
如果您懷疑程式碼中的迴圈在一定次數的迭代之後開始出現異常行為,您可以設定斷點來讓程式在達到該次數後停止執行,而不需要重複按下 F5 來達到該迭代次數。
在[斷點設定] 視窗中的[條件] 下,選取[命中次數],然後指定迴圈次數。 在下列範例中,斷點會設定為在每隔一個迭代時觸發:
設定篩選條件
您可以限制斷點僅在指定的設備上觸發,或在指定的程序和線程中觸發。
在 [斷點設定] 視窗中的 [條件] 下,選取 [篩選],然後輸入下列一或多個表達式:
- MachineName = “name”
- ProcessId = value
- ProcessName = “name”
- ThreadId = value
- ThreadName = “name”
以雙引號括住字串值。 您可以使用 &
(AND)、||
(OR)、!
(NOT) 和括弧來合併子句。
設定函式斷點
呼叫函式時,您可以中斷執行。 例如,當您知道函式名稱而非其位置時,這非常有用。 如果您有具有相同名稱的函式,而且想要將其全部中斷(例如不同專案中的多載函式或函式),它也會很有用。
若要設定函式斷點:
選取 [偵錯]>[新增斷點]>[函式斷點],或按 Ctrl + K,B。
您也可以在 [斷點] 視窗中選取 [新增>函數斷點]。
在 新增函式斷點 對話框中,於 函式名稱 方塊中輸入函式名稱。
若要縮小函式規格的範圍:
使用完整函式名稱。
範例:
Namespace1.ClassX.MethodA()
新增多載函式的參數類型。
範例:
MethodA(int, string)
使用 '!' 符號來指定模組。
範例:
App1.dll!MethodA
在原生C++中使用內容運算符。
{function, , [module]} [+<line offset from start of method>]
範例:
{MethodA, , App1.dll}+2
在 [Language] 下拉式清單中,選擇函式的語言。
選取 [確定] 。
使用記憶體位址設定函式斷點(僅限原生C++)
您可以使用 物件的位址,在類別的特定實例所呼叫的方法上設定函式斷點。 例如,假設類型為 my_class
的可尋址物件,您可以在實例所呼叫的 my_method
方法上設定函式斷點。
在具現化 類別實例之後的某處設定斷點。
尋找實例的位址(例如,
0xcccccccc
)。選取 [偵錯]、、>、、[新增斷點]、、>、、[函式斷點],或按 Ctrl + K,B。
將下列內容新增至 [函式名稱] 方塊,然後選取 [C++ 語言]。
((my_class *) 0xcccccccc)->my_method
設定資料斷點 (.NET Core 3.x 或 .NET 5+)
當特定物件的 屬性變更時,數據斷點會中斷執行。
若要設定資料斷點:
在 .NET Core 或 .NET 5+ 專案中,開始偵錯,並等到到達斷點為止。
在 [自動]、[監看式] 或 [局部變數] 視窗中,以滑鼠右鍵單擊屬性,然後在操作功能表中的值變更 時選取 [ 中斷]。
.NET Core 和 .NET 5+ 的數據斷點不適用於:
- 無法在工具提示、局部變數、自動或監看式視窗中展開的屬性
- 靜態變數
- 具有 DebuggerTypeProxy 屬性的類別
- 結構內的欄位
如您可以設定的最大數目,請參閱 資料斷點硬體限制。
設定資料斷點 (僅限原生C++)
當儲存在指定記憶體位址的值變更時,數據斷點會中斷執行。 如果值已讀取但未變更,則執行不會中斷。
若要設定資料斷點:
在C++專案中,開始偵錯,並等到到達斷點為止。 在 Debug 功能表上,選擇 新增斷點>數據斷點。
您也可以在 [斷點] 視窗中選取 [新增>數據斷點],或在 [自動]、[監看] 或 [局部變數] 視窗中的項目按右鍵,然後在操作功能表中選取 [值變更時中斷]。
在 [位址] 方塊中,輸入記憶體位址或會計算為記憶體位址的表達式。 例如,當變數
avar
的內容變更時,輸入&avar
以設置中斷點。在 [位元組計數] 下拉式清單中,選取您想要調試程式監看的位元組數目。 例如,如果您選取 4,調試程式會監看從
&avar
開始的四個字節,並在其中任一個字節變更值時中斷。
資料斷點在下列情況下無法運作:
- 未經偵錯的進程對記憶體位置進行寫入。
- 記憶體位置會在兩個或多個進程之間共用。
- 記憶體位置會在核心內更新。 例如,如果記憶體傳遞至 32 位 Windows
ReadFile
函式,記憶體會從核心模式更新,因此調試程式不會在更新時中斷。 - 其中監看表達式在 32 位硬體上大於 4 個字節,而 64 位硬體則大於 8 個字節。 這是 x86 架構的限制。
注意
數據斷點取決於特定的記憶體位址。 變數的位址會從一個偵錯會話變更為下一個,因此會在每個偵錯會話的結尾自動停用數據斷點。
如果您在局部變數上設定數據斷點,當函式結束時,斷點仍會保持啟用,但記憶體位址已不再適用,因此斷點的行為無法預測。 如果您在局部變數上設定資料斷點,您應該在函式結束時刪除或停用斷點。
數據斷點硬體限制
設定數據斷點時,Windows 核心和基礎硬體具有下列限制。 限制是指您可以設定的數據斷點數目上限。
處理器架構 | 數據斷點限制 |
---|---|
x64 和 x86 | 4 |
ARM64 | 2 |
ARM | 1 |
設定相依斷點
只有在另一個斷點先被觸發時,相依斷點才會中斷執行。 因此,在除錯多執行緒應用程式等複雜情況中,您可以在首次觸發某個斷點後,設定其他斷點。 這可以讓在遊戲迴圈或公用程式 API 等常見路徑中進行程式偵錯更容易,因為這些函式中的斷點可以被配置為只有在從應用程式的特定部分調用函式時才啟用。
若要設定相依斷點:
將滑鼠停留在斷點符號上,選擇 [設定] 圖示,然後在 [斷點設定] 視窗中,選取 [僅在命中以下斷點時啟用]。
在下拉式清單中,選取您希望目前斷點依賴的前置斷點。
選擇 關閉,或按 Ctrl+Enter 來關閉 [斷點設定] 視窗。 或者,從 [斷點] 視窗中選擇 [確定] 以關閉對話框。
您也可以使用滑鼠右鍵內容功能表來設定相依斷點。
以滑鼠右鍵單擊程式代碼行旁最左邊的邊界,然後從內容功能表中選取 [插入相依斷點]。
- 如果您的應用程式中只有單一斷點,相依斷點將無法運作。
- 如果刪除必要斷點,相依斷點會轉換成一般行斷點。
設定暫時斷點
此斷點可讓您只中斷程式代碼一次。 偵錯時,Visual Studio 偵錯工具只會針對此斷點暫停執行中的應用程式一次,然後在觸發後立即移除它。
若要設定暫時斷點:
將滑鼠停留在斷點符號上,選擇 [設定] 圖示,然後在 [斷點設定] 視窗中選取 [命中後移除斷點]。
選擇 關閉,或按 Ctrl+Enter 來關閉[斷點設定]視窗。 或者,從 [斷點] 視窗中,選擇 [確定] 來關閉對話框。
您也可以使用滑鼠右鍵選單來設定暫時斷點。
以滑鼠右鍵點擊程式代碼行旁的左邊界,然後從快捷選單選取 插入暫時斷點。
或者,只要使用快捷方式 F9 + Shift + Alt、T,並在所需的行上設定暫時斷點。
相關內容
- 什麼是偵錯?
- 使用 Visual Studio 撰寫更好的 C# 程式代碼
- 第一次查看偵錯
- 使用 Visual Studio 除錯器進行斷點疑難排解