Visual Studio調試指南---僅調試具有僅我的代碼的用戶代碼


僅我的代碼是一種 Visual Studio 調試功能,可自動執行對系統、框架和其他非用戶代碼的調用。 在 "調用堆棧" 窗口中,僅我的代碼將這些調用折疊到 [外部代碼] 幀中。在 .NET、 C++和 JavaScript 項目中,僅我的代碼的工作方式有所不同。

啟用或禁用“僅我的代碼”

對於大多數編程語言,默認情況下啟用僅我的代碼。

  • 若要在 Visual Studio 中啟用或禁用僅我的代碼,請在 "工具" > 選項"(或"調試 > 選項") >調試 > 常規",選擇或取消選擇 "啟用僅我的代碼"。

注意:啟用僅我的代碼是一項全局設置,適用於所有語言的所有 Visual Studio 項目。

“僅我的代碼”調試

在調試會話期間,"模塊" 窗口顯示調試器將哪個代碼模塊視為我的代碼(用戶代碼)以及其符號加載狀態。 

![模塊 窗口中的用戶代碼](../debugger/media/dbg_justmycode_module.png ""模塊" 窗口中的用戶代碼")

在 "調用堆棧" 或 "任務" 窗口中,僅我的代碼將非用戶代碼折疊成標記為 [External Code] 的灰色批注代碼框架。

 

若要查看折疊的 [外部代碼] 幀中的代碼,請在 "調用堆棧" 或 "任務" 窗口中單擊右鍵,然后從上下文菜單中選擇 "顯示外部代碼"。 展開的外部代碼行替換 [外部代碼] 框架。

 

在 "調用堆棧" 窗口中雙擊展開的外部代碼行會在源代碼中突出顯示以綠色顯示的調用代碼行。 對於 Dll 或未找到或加載的其他模塊,可能會打開 "符號或源找不到" 頁。

.NET 僅我的代碼

在 .NET 項目中,僅我的代碼使用符號( .pdb)文件和程序優化來對用戶和非用戶代碼進行分類。 .NET 調試器將優化的二進制文件和非加載 .pdb文件視為非用戶代碼。

這三個編譯器屬性還會影響 .NET 調試器認為是用戶代碼:

  • DebuggerNonUserCodeAttribute 通知調試器,它應用到的代碼不是用戶代碼。
  • DebuggerHiddenAttribute 對調試器隱藏代碼,即使“僅我的代碼”關閉;
  • DebuggerStepThroughAttribute 通知調試器遍歷應用到的代碼,而不是單步執行代碼。

.NET 調試器將所有其他代碼視為用戶代碼。

在 .NET 調試期間:

  • 調試 > 單步執行(或按F11)在非用戶代碼上逐過程執行代碼,並將代碼移到用戶代碼的下一行。
  • 調試 > 非用戶代碼上的 "跳出" (或Shift +F11)運行到用戶代碼的下一行。

如果沒有更多的用戶代碼,調試將繼續,直到它結束、到達另一個斷點或引發錯誤。

如果調試器在非用戶代碼中中斷(例如,在非用戶代碼中使用 "調試" > "全部中斷" 和 "暫停"),則不會顯示 "無源" 窗口。 然后,你可以使用 "調試 > 步驟" 命令來執行用戶代碼的下一行。

如果非用戶代碼中出現未經處理的異常,調試器將在生成異常的用戶代碼行處中斷。

如果對異常啟用了第一次機會異常,則調用用戶代碼行在源代碼中以綠色突出顯示。 "調用堆棧" 窗口顯示標記為 [外部代碼] 的帶批注的幀。

C++“僅我的代碼”

從 Visual Studio 2017 15.8 版開始,還支持代碼單僅我的代碼。 此功能還要求使用/JMC (僅我的代碼調試)編譯器開關。 默認情況下,在項目中C++啟用此開關。 對於 "調用堆棧" 窗口和僅我的代碼中的調用堆棧支持,不需要/JMC 開關。

若要歸類為用戶代碼,必須由調試器加載包含用戶代碼的二進制文件的 PDB (使用 "模塊" 窗口進行檢查)。

對於調用堆棧行為(如 "調用堆棧" 窗口中的), C++中的僅我的代碼僅將這些函數視為非用戶代碼:

  • 在其符號文件中去除了源信息的函數。
  • 符號文件指示沒有對應於堆棧幀的源文件的函數。
  • %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers文件夾中 * natjmc文件中指定的函數。

對於代碼單步執行行為, C++僅我的代碼僅將這些函數視為非用戶代碼:

  • 調試器中尚未加載相應的 PDB 文件的函數。
  • %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers文件夾中 * natjmc文件中指定的函數。

為了僅我的代碼中的代碼步進支持C++ ,必須在 Visual Studio 15.8 Preview 3 或更高版本中使用 MSVC 編譯器來編譯代碼,並且必須啟用/JMC 編譯器開關(默認情況下啟用)。 對於使用較舊的編譯器編譯的代碼, . natstepfilter files 是自定義代碼單步執行的唯一方法,該方法與僅我的代碼無關。

調試C++期間:

  • 調試 > 單步執行(或按F11)在非用戶代碼上逐過程執行代碼,並將代碼移到用戶代碼的下一行。
  • 調試 > 非用戶代碼上的 "跳出" (或Shift +F11)運行到用戶代碼的下一行。

如果沒有更多的用戶代碼,調試將繼續,直到它結束、到達另一個斷點或引發錯誤。

如果調試器在非用戶代碼中中斷(例如,在非用戶代碼中使用 "調試" > "全部中斷" 和 "暫停"),則在非用戶代碼中繼續執行。

如果調試器遇到異常,則它會在異常上停止,無論它是在用戶代碼還是非用戶代碼中。 "異常設置" 對話框中的用戶未處理的選項將被忽略。

自C++定義調用堆棧和代碼單步執行行為

對於C++項目,可以指定模塊、源文件和函數,"調用堆棧" 窗口將其視為非用戶代碼,方法是在 * natjmc文件中指定它們。 如果使用的是最新的編譯器,此自定義也適用於代碼單步執行(請參閱 C++僅我的代碼)。

  • 若要為 Visual Studio 計算機的所有用戶指定非用戶代碼,請將natjmc文件添加到 %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers文件夾。
  • 若要為單個用戶指定非用戶代碼,請將natjmc文件添加到 %USERPROFILE%\My 文檔 \ < Visual Studio 版本 > \visualizers文件夾中。

Natjmc文件是具有以下語法的 XML 文件:

XML
<?xml version="1.0" encoding="utf-8"?> <NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2015"> <!-- Modules --> <Module Name="ModuleSpec" /> <Module Name="ModuleSpec" Company="CompanyName" /> <!-- Files --> <File Name="FileSpec"/> <!-- Functions --> <Function Name="FunctionSpec" /> <Function Name="FunctionSpec" Module ="ModuleSpec" /> <Function Name="FunctionSpec" Module ="ModuleSpec" ExceptionImplementation="true" /> </NonUserCode> 

模塊元素屬性

表 1
特性 描述
Name 必須的。 模塊的完整路徑。 可以使用 Windows 通配符 ? (零個或一個字符)和 * (零個或多個字符)。 例如,應用於對象的

<Module Name="?:\3rdParty\UtilLibs\*" />

告知調試器中的所有模塊都視為 \3rdParty\UtilLibs 外部代碼的任何驅動器上。
Company 可選。 發布在可執行文件中嵌入的模塊的公司的名稱。 可以使用此特性消除模塊歧義。

文件元素屬性

表 2
特性 描述
Name 必須的。 要視為外部代碼的源文件的完整路徑。 可以在指定路徑時使用 Windows 通配符 ?*

函數元素屬性

表 3
特性 描述
Name 必須的。 要視為外部代碼的函數的完全限定的名稱。
Module 可選。 包含函數的模塊的名稱或完整路徑。 可以使用此特性區分具有相同名稱的函數。
ExceptionImplementation 設置為 true 時,調用堆棧顯示的是引發異常的函數,而不是此函數。

自C++定義獨立於僅我的代碼設置的單步執行行為

在C++項目中,可以通過將函數作為 * 文件中的非用戶代碼列出來指定要逐過程執行的函數。 *@No__t_1*文件中列出的函數不依賴於僅我的代碼設置。

  • 若要為所有本地 Visual Studio 用戶指定非用戶代碼,請將natstepfilter文件添加到 %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers文件夾。
  • 若要為單個用戶指定非用戶代碼,請將natstepfilter文件添加到 %USERPROFILE%\My 文檔 \ < Visual Studio 版本 > \visualizers文件夾中。

Natstepfilter文件是具有以下語法的 XML 文件:

XML
<?xml version="1.0" encoding="utf-8"?> <StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010"> <Function> <Name>FunctionSpec</Name> <Action>StepAction</Action> </Function> <Function> <Name>FunctionSpec</Name> <Module>ModuleSpec</Module> <Action>StepAction</Action> </Function> </StepFilter> 

 

表 4
元素 描述
Function 必須的。 將一個或多個函數指定為非用戶函數。
Name 必須的。 ECMA-262 格式的正則表達式,指定要匹配的完整函數名。 例如:

<Name>MyNS::MyClass.*</Name>

告知調試器將 MyNS::MyClass 中的所有方法都視為非用戶代碼。 匹配區分大小寫。
Module 可選。 ECMA-262 格式的正則表達式,指定包含函數的模塊的完整路徑。 匹配不區分大小寫。
Action 必須的。 以下區分大小寫的值之一:

NoStepInto-通知調試器逐過程執行該函數。
StepInto-通知調試器單步執行函數,並重寫匹配函數的任何其他 NoStepInto


免責聲明!

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



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