Поделиться через


Метод 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] Идентификатор целевого потока.

Передача значения NULL в thread возвращает snapshot текущего потока. ThreadID Если передается из другого потока, среда CLR приостанавливает этот поток, выполняет snapshot и возобновляет работу.

callback
[in] Указатель на реализацию метода StackSnapshotCallback , который вызывается средой CLR для предоставления профилировщику сведений о каждом управляемом кадре и каждом запуске неуправляемых кадров.

Метод StackSnapshotCallback реализуется модулем записи профилировщика.

infoFlags
[in] Значение перечисления COR_PRF_SNAPSHOT_INFO, указывающее объем данных, передаваемых обратно для каждого кадра .StackSnapshotCallback

clientData
[in] Указатель на данные клиента, который передается непосредственно в функцию обратного StackSnapshotCallback вызова.

context
[in] Указатель на структуру Win32 CONTEXT , которая используется для заполнения шага стека. Структура Win32 CONTEXT содержит значения регистров ЦП и представляет состояние ЦП на определенный момент времени.

Начальное значение помогает среде CLR определить, с чего начать пошаговое руководство по стеку, если в верхней части стека находится неуправляемый вспомогательный код; В противном случае начальное значение игнорируется. Начальное значение должно быть предоставлено для асинхронной прогулки. Если вы выполняете синхронную прогулку, начальное значение не требуется.

Параметр context действителен, только если в infoFlags параметре был передан флаг COR_PRF_SNAPSHOT_CONTEXT.

contextSize
[in] Размер CONTEXT структуры, на которую ссылается context параметр .

Комментарии

Передача значения NULL для thread возвращает snapshot текущего потока. Моментальные снимки могут быть сделаны из других потоков, только если целевой поток приостановлен в то время.

Когда профилировщик хочет пройти по стеку, он вызывает DoStackSnapshot. Прежде чем среда CLR возвращается из этого вызова, она вызывает несколько StackSnapshotCallback раз, по одному разу для каждого управляемого кадра (или запуска неуправляемых кадров) в стеке. При обнаружении неуправляемых кадров их необходимо выполнять самостоятельно.

Порядок, в котором выполняется проход по стеку, является обратным образом того, как кадры были наложены на стек: сначала конечный (последний толкаемый) кадр, main (первый толкаемый) кадр последний.

Дополнительные сведения о том, как запрограммировать профилировщик для обхода управляемых стеков, см. в разделе Профилировщик стека Walk в платформа .NET Framework 2.0. Основные сведения и более подробные сведения.

Пошаговое руководство по стеку может быть синхронным или асинхронным, как описано в следующих разделах.

Синхронное пошаговое руководство по стеку

Синхронное пошаговое руководство по стеку включает в себя обход стека текущего потока в ответ на обратный вызов. Он не требует заполнения или приостановки.

Выполняется синхронный вызов, когда в ответ на вызов среды CLR одного из методов ICorProfilerCallback (или ICorProfilerCallback2) профилировщика вызывается DoStackSnapshot для обхода стека текущего потока. Это полезно, если вы хотите увидеть, как выглядит стек в уведомлении, например ICorProfilerCallback::ObjectAllocated. Вы просто вызываете DoStackSnapshotICorProfilerCallback из метода , передавая значение NULL в параметрах context и thread .

Асинхронное пошаговое руководство по стек

Асинхронная прогулка по стеку подразумевает обход стека другого потока или стек текущего потока не в ответ на обратный вызов, а путем перехвата указателя инструкций текущего потока. Для асинхронного пошагового выполнения требуется начальное значение, если в верхней части стека находится неуправляемый код, который не является частью вызова платформы (PInvoke) или COM-вызова, а вспомогательным кодом в самой среде CLR. Например, код, который выполняет JIT-компиляцию или сборку мусора, является вспомогательным кодом.

Начальное значение можно получить, напрямую приостановив целевой поток и самостоятельно пройдя его стек, пока не найдете самый верхний управляемый кадр. После приостановки целевого потока получите текущий контекст регистра целевого потока. Затем определите, указывает ли контекст регистра на неуправляемый код, вызвав метод ICorProfilerInfo::GetFunctionFromIP — если он возвращает значение, равное FunctionID нулю, кадр является неуправляемым кодом. Теперь пройдите по стеку, пока не достигнете первого управляемого кадра, а затем вычислите начальный контекст на основе контекста регистра для этого кадра.

Вызовите DoStackSnapshot с начальным контекстом, чтобы начать асинхронное пошаговое руководство по стеку. Если не указать начальное значение, DoStackSnapshot можно пропустить управляемые кадры в верхней части стека и, следовательно, получить неполный обход стека. Если вы предоставляете начальное значение, оно должно указывать на JIT-скомпилированный или собственный генератор образов (Ngen.exe) код; В противном DoStackSnapshot случае возвращает код сбоя CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.

Асинхронные обходы стека могут легко привести к взаимоблокировкам или нарушениям доступа, если не следовать следующим рекомендациям:

  • При непосредственной приостановке потоков помните, что только поток, который никогда не выполнял управляемый код, может приостановить другой поток.

  • Всегда блокируйте обратный вызов ICorProfilerCallback::ThreadDeкиed , пока не завершится обход стека этого потока.

  • Не удерживайте блокировку, пока профилировщик вызывает функцию CLR, которая может активировать сборку мусора. Это значит, что не удерживайте блокировку, если владеющий поток может выполнить вызов, который активирует сборку мусора.

Кроме того, существует риск взаимоблокировки при вызове DoStackSnapshot из потока, созданного профилировщиком, чтобы можно было пройти по стеку отдельного целевого потока. При первом входе созданного потока в определенные ICorProfilerInfo* методы (включая DoStackSnapshot), среда CLR будет выполнять инициализацию для каждого потока, зависящее от среды CLR, в этом потоке. Если профилировщик приостановил целевой поток, стек которого вы пытаетесь пройти, и если этот целевой поток получил блокировку, необходимую для выполнения этой инициализации каждого потока, возникнет взаимоблокировка. Чтобы избежать этой взаимоблокировки, выполните первоначальный вызов DoStackSnapshot из потока, созданного профилировщиком, чтобы пройти отдельный целевой поток, но не приостанавливайте его сначала. Этот начальный вызов гарантирует, что инициализация каждого потока может завершиться без взаимоблокировки. Если DoStackSnapshot выполняется успешно и сообщается по крайней мере один кадр, после этого будет безопасно для этого потока, созданного профилировщиком, приостановить любой целевой поток и вызвать для DoStackSnapshot обхода стека этого целевого потока.

Требования

Платформы: см. раздел Требования к системе.

Заголовок: CorProf.idl, CorProf.h

Библиотека: CorGuids.lib

версии платформа .NET Framework: доступно с версии 2.0.

См. также раздел