ICorProfilerInfo2::DoStackSnapshot 方法

查核指定執行緒堆疊上的受控框架,並透過回呼將資訊傳送至分析工具。

語法

HRESULT DoStackSnapshot(  
    [in] ThreadID thread,  
    [in] StackSnapshotCallback *callback,  
    [in] ULONG32 infoFlags,  
    [in] void *clientData,  
    [in, size_is(contextSize), length_is(contextSize)] BYTE context[],  
    [in] ULONG32 contextSize);  

參數

thread
[in] 目標執行緒的識別碼。

thread 中傳遞 null 會產生目前執行緒的快照集。 如果傳遞了不同執行緒的 ThreadID,Common Language Runtime (CLR) 會暫止該執行緒、執行快照集並繼續。

callback
[in] StackSnapshotCallback 方法實作的指標,CLR 會呼叫此方法,為分析工具提供每個受控框架和每次執行未受控框架的資訊。

StackSnapshotCallback 方法是由偵錯工具寫入器實作。

infoFlags
[in] COR_PRF_SNAPSHOT_INFO 列舉的值,指定要透過 StackSnapshotCallback 針對每個框架傳回的資料量。

clientData
[in] 用戶端資料的指標,會直接傳遞至 StackSnapshotCallback 回呼函式。

context
[in] Win32 CONTEXT 結構的指標,用來對堆疊查核植入種子。 Win32 CONTEXT 結構包含 CPU 暫存器的值,並代表特定時間點的 CPU 狀態。

如果堆疊頂端是非受控協助程式的程式碼,此種子可協助 CLR 判斷要開始堆疊查核的位置;否則會忽略種子。 必須針對非同步查核提供種子。 如果您要進行同步查核,則不需要種子。

只有在 infoFlags 參數中傳遞 COR_PRF_SNAPSHOT_CONTEXT 旗標時,context 參數才有效。

contextSize
[in] context 參數所參考的 CONTEXT 結構大小。

備註

thread 傳遞 null 會產生目前執行緒的快照集。 只有在目標執行緒暫止當下,才能擷取其他執行緒的快照集。

當分析工具想要查核堆疊時,它會呼叫 DoStackSnapshot。 該呼叫傳回 CLR 之前,它會呼叫您的 StackSnapshotCallback 數次,針對堆疊上的每個受控框架 (或執行非受控框架) 呼叫一次。 遇到非受控框架時,您必須自行查核。

查核堆疊的順序是框架推送至堆疊的反向方式:先分葉 (最後推送) 框架,最後是主要 (最先推送) 框架。

如需如何程式設計分析工具以逐步執行 Managed 堆疊的詳細資訊,請參閱.NET Framework 2.0 中的分析工具堆疊逐步解說:基本概念和更新版本。

堆疊查核可以是同步或非同步,如下列各節所述。

同步堆疊查核

同步堆疊查核牽涉到查核目前執行緒的堆疊,以回應回呼。 它不需要植入或暫止。

當您呼叫 DoStackSnapshot 查核目前執行緒的堆疊,以回應 CLR 呼叫分析工具的 ICorProfilerCallback(或 ICorProfilerCallback2) 方法其中之一時,您可進行同步呼叫。 當您想要查看在如 ICorProfilerCallback::ObjectAllocated 之通知的堆疊樣貌時,這非常有用。 您只要從 ICorProfilerCallback 方法內呼叫 DoStackSnapshot,並在 contextthread 參數中傳遞 null。

非同步堆疊查核

非同步堆疊查核表示查核不同執行緒的堆疊,或查核目前執行緒的堆疊,不是回應回呼,而是攔截目前執行緒的指令指標。 如果堆疊頂端不是平台叫用 (PInvoke) 或 COM 呼叫,但 CLR 本身協助程式的程式碼不是平台叫用的一部分,則非同步查核需要種子。 例如,執行 Just-In-Time (JIT) 編譯或記憶體回收的程式碼,是協助程式的程式碼。

您可以直接暫止目標執行緒並自行查核堆疊,以取得種子,直到您找到最上層受控框架為止。 在目標執行緒暫止之後,取得目標執行緒目前的暫存器內容。 接下來,藉由呼叫 ICorProfilerInfo::GetFunctionFromIP 來判斷暫存器內容是否指向非受控程式碼,如果它傳回 FunctionID 等於零,則框架為非受控程式碼。 現在,請查核堆疊,直到您到達第一個受控框架,然後根據該框架的暫存器內容來計算種子內容。

使用種子內容呼叫 DoStackSnapshot,以開始非同步堆疊查核。 如果您未提供種子,DoStackSnapshot 可能會略過堆疊頂端的受控框架,因此將會提供不完整的堆疊查核。 如果您提供種子,它必須指向 JIT 編譯或 Native Image Generator (Ngen.exe) 產生的程式碼;否則,DoStackSnapshot 會傳回失敗碼 CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX。

除非您遵循下列指導方針,否則非同步堆疊查核會很容易造成死結或存取違規:

  • 當您直接暫止執行緒時,請記住只有從未執行受控程式碼的執行緒才能暫止另一個執行緒。

  • 一律封鎖 ICorProfilerCallback::ThreadDestroyed 中的回呼,直到該執行緒的堆疊查核完成為止。

  • 當分析工具呼叫可觸發記憶體回收的 CLR 函式時,請勿保留鎖定。 也就是說,如果擁有執行緒可能會觸發記憶體回收的呼叫,請勿保留鎖定。

如果您從分析工具所建立的執行緒呼叫 DoStackSnapshot,以便您可以查核個別目標執行緒的堆疊,也會有死結的風險。 第一次建立的執行緒進入特定 ICorProfilerInfo* 方法時 (包括 DoStackSnapshot),CLR 會在該執行緒上執行個別執行緒、CLR 特定的初始化。 如果您的分析工具已暫止您嘗試查核其堆疊的目標執行緒,而且如果該目標執行緒擁有執行此個別執行緒初始化所需的鎖定,就會發生死結。 若要避免這種死結,請從分析工具建立的執行緒進行初始呼叫 DoStackSnapshot,以查核個別的目標執行緒,但不要先暫止目標執行緒。 此初始呼叫可確保每個執行緒初始化可以在沒有死結的情況下完成。 如果 DoStackSnapshot 成功並報告至少一個框架,在該時間點之後,該分析工具建立的執行緒將可安全暫止任何目標執行緒,並呼叫 DoStackSnapshot 來查核該目標執行緒的堆疊。

規格需求

平台:請參閱系統需求

標頭: CorProf.idl、CorProf.h

程式庫:CorGuids.lib

.NET Framework版本:自 2.0 起可用

另請參閱