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
,並在 context
和 thread
參數中傳遞 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 起可用