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] 대상 스레드의 ID입니다.

thread에 null을 전달하면 현재 스레드의 스냅샷이 생성됩니다. 다른 스레드의 ThreadID가 전달되면 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에서 스택 워크를 시작할 위치를 결정할 수 있습니다. 그렇지 않으면 시드가 무시됩니다. 비동기 워크에는 시드를 제공해야 합니다. 동기식 워크를 수행하는 경우 시드가 필요하지 않습니다.

context 매개 변수는 COR_PRF_SNAPSHOT_CONTEXT 플래그가 infoFlags 매개 변수에 전달된 경우에만 유효합니다.

contextSize
[in] context 매개 변수에서 참조하는 CONTEXT 구조체의 크기입니다.

설명

thread에 대해 null을 전달하면 현재 스레드의 스냅샷이 생성됩니다. 대상 스레드가 일시 중단된 경우에만 다른 스레드의 스냅샷을 만들 수 있습니다.

프로파일러가 스택을 안내하려고 할 때 DoStackSnapshot을 호출합니다. 해당 호출에서 CLR이 반환되기 전에 스택의 각 관리 프레임(또는 비관리 프레임 실행)에 대해 한 번씩 StackSnapshotCallback을 여러 번 호출합니다. 비관리 프레임이 발생하면 직접 안내해야 합니다.

스택이 안내하는 순서는 프레임이 스택에 푸시된 방식의 반대입니다. 즉, 리프(마지막으로 푸시된) 프레임이 먼저이고 기본(첫 번째로 푸시된) 프레임이 마지막입니다.

관리 스택을 안내하도록 프로파일러를 프로그래밍하는 방법에 대한 자세한 내용은 .NET Framework 2.0의 프로파일러 스택 워킹: 기본 사항 및 그 이상을 참조하세요.

스택 워크는 다음 섹션에서 설명하는 것처럼 동기식 또는 비동기식일 수 있습니다.

동기식 스택 워크

동기식 스택 워크에는 콜백에 대한 응답으로 현재 스레드의 스택이 포함됩니다. 시딩이나 일시 중단이 필요하지 않습니다.

프로파일러의 ICorProfilerCallback(또는 ICorProfilerCallback2) 메서드 중 하나를 호출하는 CLR에 대한 응답으로 DoStackSnapshot을 호출하여 현재 스레드의 스택을 안내할 때 동기 호출을 수행합니다. 이는 ICorProfilerCallback::ObjectAllocated와 같은 알림에서 스택이 어떻게 보이는지 확인하려는 경우에 유용합니다. contextthread 매개 변수에 null을 전달하여 ICorProfilerCallback 메서드 내에서 DoStackSnapshot을 호출하기만 하면 됩니다.

비동기 스택 워크

비동기 스택 워크는 콜백에 대한 응답이 아니라 현재 스레드의 명령 포인터를 하이재킹하여 다른 스레드의 스택을 안내하거나 현재 스레드의 스택을 안내하는 것을 수반합니다. 스택의 맨 위가 플랫폼 호출(PInvoke) 또는 COM 호출의 일부가 아니라 CLR 자체의 도우미 코드인 관리되지 않는 코드인 경우 비동기 워크에는 시드가 필요합니다. 예를 들어 JIT(Just-In-Time) 컴파일 또는 가비지 수집을 수행하는 코드는 도우미 코드입니다.

최상위 관리 프레임을 찾을 때까지 대상 스레드를 직접 일시 중단하고 스택을 직접 안내하여 시드를 얻습니다. 대상 스레드가 일시 중단된 후 대상 스레드의 현재 레지스터 컨텍스트를 가져옵니다. 그런 다음 ICorProfilerInfo::GetFunctionFromIP를 호출하여 레지스터 컨텍스트가 비관리 코드를 가리키는지 여부를 확인합니다. FunctionID가 0으로 반환되면 프레임은 비관리 코드입니다. 이제 첫 번째 관리 프레임에 도달할 때까지 스택을 안내한 다음 해당 프레임에 대한 레지스터 컨텍스트를 기반으로 시드 컨텍스트를 계산합니다.

시드 컨텍스트로 DoStackSnapshot을 호출하여 비동기 스택 워크를 시작합니다. 시드를 제공하지 않으면 DoStackSnapshot이 스택 맨 위에서 관리 프레임을 건너뛸 수 있으며 결과적으로 불완전한 스택 워크를 제공합니다. 시드를 제공하는 경우 JIT 컴파일 또는 네이티브 이미지 생성기(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부터 사용 가능

참고 항목