CLR 偵錯概觀
Common Language Runtime (CLR) 偵錯 API 可讓工具廠商撰寫偵錯工具,以便對 CLR 環境中執行的應用程式進行偵錯。 要偵錯的程式碼可以是 CLR 支援之任何種類的程式碼。
CLR 偵錯 API 主要是使用 Unmanaged 程式碼來實作。 因此,偵錯 API 會以一組元件物件模型 (COM) 介面形式呈現。 此 API 由下列項目組成:
CLR 實作的 COM 物件和介面集合。
偵錯工具必須實作的回呼介面集合。
本概觀包含下列各節:
CLR 偵錯案例
API 分類
附加至或啟動程式
控制執行
檢查程式狀態
修改程式狀態
使用編輯後繼續
評估函式
動態插入程式碼
支援的環境
相關主題
CLR 偵錯案例
下列各節說明 Common Language Runtime 偵錯 API 處理一般偵錯案例的方法。 請注意,此 Runtime 直接支援某些案例,並與目前的方法交互操作,以支援其他案例。
跨處理序偵錯 (Out-Of-Process Debugging)
在跨處理序偵錯中,偵錯工具所在的處理序會與已執行偵錯的處理序隔開 (也就是,在偵錯項外部)。 這個案例會降低偵錯工具和偵錯項之間的互動。 因此,可以更精確地描述處理序。
CLR 偵錯 API 會直接支援跨處理序偵錯。 API 會處理偵錯工具和偵錯項之 Managed 部分間的所有通訊,以支援 Managed 程式碼偵錯。
雖然 CLR 偵錯 API 使用跨處理序,有些偵錯邏輯 (例如,執行序同步處理) 會在偵錯項的同處理序 (In-Process) 中發生。 在多數情況下,對偵錯工具來說,這應該是透明的實作詳細資料。 如需執行緒同步處理的詳細資訊,請參閱 CLR 偵錯架構。 缺點是,偵錯 API 無法在跨處理序使用時,用以檢查損毀傾印 (Crash Dump)。
同處理序偵錯
在 .NET Framework 1.0 和 1.1 版中,CLR 偵錯 API 支援有限的同處理序偵錯,而在這種偵錯中,分析工具可以使用偵錯 API 的檢查功能。 在 .NET Framework 2.0 中,同處理序偵錯已由一組與分析 API 更一致的功能所取代。 如需這些變更的詳細資訊,請參閱分析概觀中的堆疊快照和物件檢查功能。
遠端處理序偵錯
在遠端處理序偵錯中,偵錯工具使用者介面會位於與所要偵錯之處理序不同的電腦上。 當偵錯工具與偵錯項目在同一部電腦執行時,若偵錯工具干擾到偵錯項目,這個案例可能會很有用。 可能造成干擾的原因如下:
資源有限。
位置相依性。
發生干擾作業系統的 Bug。
CLR 偵錯 API 不支援直接遠端處理序偵錯。 以 CLR 偵錯 API 為基礎的偵錯工具,仍必須存在於偵錯項的跨處理序中。 因此,這個解決方案在與偵錯項目相同的電腦上需要 Proxy 處理序。
Unmanaged 程式碼偵錯
Managed 程式碼和 Unmanaged 程式碼通常共存於同一個處理序。 同時偵錯這兩種程式碼是常見的需求。
CLR 偵錯 API 支援逐步執行 Managed 和 Unmanaged 程式碼之間的界限,但無法直接支援 Unmanaged 程式碼偵錯。 不過,CLR 偵錯 API 可以透過共用 Win32 偵錯功能,與 Unmanaged 程式碼偵錯工具共存。
CLR 偵錯 API 更進一步提供兩個可偵錯處理序的選項:
「軟附加」(Soft-attach) 選項,只會偵錯處理序的 Managed 部分。 軟附加至處理序的偵錯工具接著可以從處理序中斷連結。
「硬附加」(Hard-attach) 選項,會偵錯處理序的 Managed 和 Unmanaged 部分,並透過偵錯 API 公開所有 Win32 偵錯事件。
混合語言環境
在元件軟體中,可以使用不同的語言建置不同的元件。 偵錯工具必須了解語言的差異,才能以正確的格式顯示資料,並以正確的語法評估運算式等等。
由於 CLR 沒有來源語言的概念,因此 CLR 偵錯 API 不提供混合語言環境的直接支援。 偵錯工具現有的來源對應機能,可以讓它將所提供的函式對應到實作該函式的語言。
多重處理序與分散式程式
元件程式可以包括合作元件,這些元件會在不同的處理序中執行,甚至在網路上不同的電腦上執行。 偵錯工具必須能夠追蹤處理序和電腦之間的執行邏輯,才能提供現在所進行動作的邏輯觀點。
CLR 偵錯 API 不支援多重處理序偵錯的直接支援。 因此,使用 API 的偵錯工具應該直接提供這類支援,而執行此動作的現有方法應該繼續執行。
回到頁首
API 分類
偵錯 API 包括下列三組介面,這三組介面一般是由 CLR 偵錯工具所使用,並會當做 Unmanaged 程式碼來實作:
支援 CLR 應用程式偵錯的介面。
提供存取符號偵錯資訊 (Symbolic Debug Information) 的介面,一般會存放在程式資料庫 (PDB) 檔案中。
支援在電腦上查詢處理序和應用程式定義域的介面。
偵錯 API 會仰賴兩組額外的介面:
中繼資料 API,可處理靜態程式資訊 (例如類別和方法型別資訊) 的檢查。
符號存放區 API,可支援 Managed 程式碼偵錯工具的來源層級偵錯。
偵錯介面也可以組織到下表顯示的功能分類中。
API 分類 |
說明 |
---|---|
登錄 |
發生特定事件時,偵錯工具會呼叫這些介面以登錄 CLR,並要求告知。 |
告知 |
回呼介面,CLR 會使用這些介面來告知各種事件的偵錯工具,並傳回所要求的資訊。 這些介面都必須由偵錯工具來實作。 |
中斷點 |
偵錯工具會呼叫這些介面,以擷取中斷點的相關資訊。 |
執行 |
偵錯工具會呼叫這些介面,以控制偵錯項目的執行並存取呼叫堆疊。 |
資訊 |
偵錯工具會呼叫這些介面,以取得偵錯項目的相關資訊。 |
列舉型別 |
偵錯工具會呼叫這些介面以列舉物件。 |
修改 |
偵錯工具會呼叫這些介面,修改已經過偵錯的程式碼。 |
下列各節說明 Common Language Runtime (CLR) 偵錯服務提供的功能。
回到頁首
附加至或啟動程式
CLR 讓您將偵錯工具附加至執行中的程式或啟動處理序。 CLR 偵錯服務讓您將偵錯工具附加至會擲回未處理例外狀況的程式,藉以支援 Just-In-Time (JIT) 偵錯。 不過,不在可偵錯模式中執行的程式可能有較少的偵錯資訊。 程式一定可以在可偵錯模式中執行,以避免這個問題。 如需可偵錯模式的詳細資訊,請參閱下列主題:
回到頁首
控制執行
CLR 偵錯服務提供了數個控制程式執行的方式。 這些包括中斷點、逐步執行、例外狀況告知、函式評估,以及其他與程式之啟動和關機相關的事件。
CLR 偵錯 API 只針對 Managed 程式碼提供了執行控制。 如果您想要執行 Unmanaged 程式碼執行控制,必須在偵錯工具中個別實作該功能。
中斷點
藉由指定程式碼和應中斷所在位置的 Microsoft Intermediate Language (MSIL) 或原生位移,便可以建立中斷點。 然後遇到中斷點時,就會告知偵錯工具。 偵錯 API 無法直接支援條件中斷點。 不過,偵錯工具可以藉由評估運算式以回應中斷點,並決定是否要將此停止告知使用者,來實作這些條件中斷點。
逐步執行
CLR 偵錯服務提供了各種逐步執行功能。 程式可以每次一個指令 (「逐步執行」(Single-Stepping)) 或每次一個指令範圍 (「範圍逐步執行」(Range-Stepping)),來逐步執行程式碼。 它可以略過、逐步執行或跳離函式。 如果發生例外狀況,因而中斷逐步執行操作,CLR 偵錯服務也會告知偵錯工具。
雖然偵錯服務不會直接支援逐步執行 Unmanaged 程式碼,但是當逐步執行作業到達 Unmanaged 程式碼時,它們會提供回呼,將控制權交給偵錯工具。 它們也提供了功能,可讓偵錯工具判斷何時即將從 Unmanaged 程式碼進入 Managed 程式碼。
CLR 不會直接提供來源層級逐步執行。 偵錯工具可以藉由使用範圍逐步執行與它本身的來源對應資訊,提供這項功能。 您可以使用符號存放區介面來取得來源層級資訊。 如需這些介面的詳細資訊,請參閱診斷符號存放區 (Unmanaged API 參考)。
例外狀況
CLR 偵錯服務會將 Managed 程式碼中的第一個可能發生和第二個可能發生的例外狀況告知偵錯工具。 擲回的物件在每個點上都可供檢查。
CLR 不會處理 Unmanaged 程式碼中的原生例外狀況,除非它們傳播到 Managed 程式碼。 不過,您仍然可以使用與 CLR 偵錯服務共用的 Win32 偵錯服務,來處理 Unmanaged 例外狀況。
程式事件
當發生許多程式事件時,CLR 偵錯服務會告知偵錯工具。 這些事件包含處理序建立和結束、執行緒建立和結束、應用程式定義域建立和結束、組件載入和卸載、模組載入和卸載,以及類別載入和卸載。 為了保證良好效能,您可以停用模組的類別載入和卸載事件。 預設會停用類別載入和卸載事件。
執行緒控制
CLR 偵錯服務提供了暫止及繼續個別 (Managed) 執行緒的介面。
回到頁首
檢查程式狀態
CLR 偵錯服務提供了詳盡方式,可在處理序處於停止狀態時檢查處理序中正在執行 Managed 程式碼的各個部分。 可檢查處理序來取得實際執行緒的清單。
可檢查執行緒,以檢查其呼叫堆疊。 執行緒的呼叫堆疊以兩個層級分解:鏈結層級和堆疊框架層級。 呼叫堆疊會先分解為鏈結。 鏈結是連續的邏輯呼叫堆疊區段。 鏈結包含 Managed 或 Unmanaged 堆疊框架,但不會同時包含兩者。 此外,單一鏈結中的所有 Managed 呼叫框架都會共用相同的 CLR 內容。 鏈結可以是 Managed 或 Unmanaged。
每個 Managed 鏈結可以再分解為單一堆疊框架。 每個堆疊框架代表一個方法引動過程。 您可以查詢堆疊框架,取得它正在執行的程式碼,或取得它的引數、區域變數和原生暫存器。
Unmanaged 鏈結不包含堆疊框架, 但會提供配置給 Unmanaged 程式碼的堆疊位址範圍。 要解碼堆疊的 Unmanaged 部分及提供堆疊追蹤是由 Unmanaged 程式碼偵錯工具決定。
注意事項 |
---|
CLR 偵錯服務不支援區域變數出現在原始程式碼的概念。將區域變數對應至其配置係由偵錯工具決定。 |
CLR 偵錯服務也會提供存取全域、類別靜態和執行緒區域變數。
回到頁首
修改程式狀態
CLR 偵錯服務會讓偵錯工具在執行期間變更指令指標的實體位置,但這是危險作業。 當下列條件為真時,可成功變更指令指標:
目前的指令指標和目標指令指標都在序列點。 序列點約略代表陳述式界限。
目標指令指標不在例外狀況篩選條件、catch 區塊或 finally 區塊中。
目前的指令指標在 catch 區塊中,而且目標指令指標不在 catch 區塊之外。
目標指令指標和目前的指令指標位在相同框架中。
當指令指標的實體位置變更時,目前指令指標位置上的變數將會對應至目標指令指標位置上的變數。 目標指令指標位置上的記憶體回收參考會正確初始化。
在變更指令指標之後,CLR 偵錯服務會將任何快取的堆疊資訊標示為無效,並在下次需要時重新整理此資訊。 快取堆疊資訊 (例如框架和鏈結) 之指標的偵錯工具應在變更指令指標後重新整理此資訊。
偵錯工具也可以在程式停止時修改程式資料。 當函式正在執行時,偵錯工具可以變更函式的區域變數和引數,方式與檢查時類似。 偵錯工具也可以更新陣列和物件欄位,還可以更新靜態欄位和全域變數。
回到頁首
使用編輯後繼續
在偵錯工作階段期間,您可以使用 [編輯後繼續] 功能來執行下列作業:
編輯原始程式碼。
重新編譯已修改的原始檔。
保留偵錯中可執行檔其餘的執行階段狀態。
繼續偵錯工作階段,而不需要從頭重新執行可執行檔。
回到頁首
評估函式
若要評估使用者運算式和物件的動態屬性,偵錯工具需要方式來執行偵錯中之處理序的程式碼。 CLR 偵錯服務可讓偵錯工具執行函式或方法呼叫,並讓它在偵錯項目的處理序中執行。
由於這種作業具危險性 (例如,可能觸發現有的程式碼死結),CLR 會讓偵錯工具停止它。 如果成功停止評估,除了部分評估在區域變數上造成的任何副作用外,會將執行緒視為從未被評估過。 如果函式以特定方式呼叫 Unmanaged 程式碼或區塊,可能無法結束評估。
完成函式評估時,CLR 會使用回呼告知偵錯工具,是否正確完成評估或函式擲回例外狀況。 您可以使用 ICorDebugValue 和 ICorDebugValue2 方法來檢查評估結果。
要進行函式評估的執行緒必須是在 Managed 程式碼中可安全執行記憶體回收的點停止 (未處理的例外狀況也可以進行函式評估)。在未最佳化的程式碼中,這些安全點非常普遍,大部分的中斷點或 MSIL 層級逐步執行作業都會在其中一點完成。 不過,在最佳化程式碼中這些點很少見。 有時候,整個函式可能沒有任何安全點。 安全點 (亦即,可安全執行記憶體回收) 的頻率因函式而異。 即使在未最佳化的程式碼中,也可能無法在其中一點停止。 無論在最佳化或未最佳化的程式碼中,ICorDebugController::Stop 方法很少有安全點。
CLR 偵錯服務會在執行緒上設定新鏈結,以啟動函式評估及呼叫所要求的函式。 評估一經啟動,偵錯 API 的所有層面就可供使用:執行控制、檢查、函式評估等等。 也支援巢狀評估,並會照常處理中斷點。
回到頁首
動態插入程式碼
有些偵錯工具會讓使用者在 [即時運算] 視窗中輸入任意陳述式及執行陳述式。 CLR 偵錯服務支援這個案例。 在合理的範圍內,並沒有限制哪些程式碼可動態插入 (例如,不允許非本機 goto 陳述式)。
透過 [編輯後繼續] 作業和函式評估的組合,實作動態程式碼插入。 以函式包裝要插入的程式碼,並透過 [編輯後繼續] 插入此程式碼。 然後評估插入的函式。 必要時,您可以將 ByRef 引數提供給包裝函式,好讓副作用即時和永久。
回到頁首
支援的環境
CLR 偵錯機能可在 CLR 支援的所有處理器和作業系統上使用,例外如下所示:
64 位元的作業系統不支援「編輯後繼續」和混合模式的偵錯。 SetIP 方法 (ICorDebugILFrame::SetIP 和 ICorDebugNativeFrame::SetIP) 在 64 位元作業系統上有其他限制。 其餘功能在所有處理器上都相同 (雖然會有處理器專有的資料表示,例如指標大小、暫存器內容等)。
Win9x 作業系統不支援「編輯後繼續」和混合模式的偵錯。 其餘功能在所有作業系統上應該相同。 不過,還是有一些特定例外,而這些例外記載於個別功能的文件中。
回到頁首
相關主題
標題 |
說明 |
---|---|
描述 CLR 偵錯 API 的不同元件與 CLR 和偵錯工具的互動方式。 |
|
描述在 .NET Framework 2.0 版中,偵錯程序的變更與改進。 |
|
說明有些 CLR 偵錯介面會如何要求將已經過偵錯的處理序設為特定的狀態。 |
|
提供了如何偵錯執行階段處理序的逐步說明。 |
|
說明偵錯工具如何使用 CLR 偵錯 API 來設定中斷點、逐步執行 Managed 和 Unmanaged 程式碼,以及處理例外狀況。 |
|
說明偵錯工具如何使用 CLR 偵錯 API 來存取 Managed 堆疊框架及評估運算式。 |
|
說明動態程式碼插入,CLR 用它來挾持使用中執行緒,以執行不在原始可攜式可執行檔 (PE) 中的程式碼。 |
|
摘要說明 CLR 處理序發行介面,這些介面會列舉及提供電腦上處理序和應用程式定義域的相關資訊。 |
|
討論使用 CLR 偵錯 API 的安全性考量。 |
|
描述偵錯 API 使用的 Unmanaged coclass。 |
|
說明 Unmanaged 介面,這類介面會處理 Common Language Runtime 中所執行之程式的偵錯。 |
|
描述偵錯 API 使用的 Unmanaged 全域靜態函式。 |
|
描述偵錯 API 使用的 Unmanaged 列舉型別。 |
|
描述偵錯 API 使用的 Unmanaged 結構。 |
回到頁首