다음을 통해 공유


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] 각 관리되는 프레임과 관리되지 않는 프레임의 각 실행에 대한 정보를 프로파일러에 제공하기 위해 CLR에서 호출하는 StackSnapshotCallback 메서드의 구현에 대한 포인터입니다.

    StackSnapshotCallback 메서드는 프로파일러 작성기에서 구현합니다.

  • infoFlags
    [in] StackSnapshotCallback에서 각 프레임에 대해 전달할 데이터 양을 지정하는 COR_PRF_SNAPSHOT_INFO 열거형의 값입니다.

  • clientData
    [in] StackSnapshotCallback 콜백 함수에 직접 전달되는 클라이언트 데이터에 대한 포인터입니다.

  • context
    [in] 스택 워크를 시드하는 데 사용되는 Win32 CONTEXT 구조체에 대한 포인터입니다. Win32 CONTEXT 구조체는 CPU 레지스터의 값을 포함하며 특정 시점의 CPU 상태를 나타냅니다.

    스택의 맨 위에 관리되지 않는 도우미 코드가 있으면 시드는 CLR에서 스택 워크를 시작할 위치를 결정하는 데 사용되고, 그렇지 않으면 시드가 무시됩니다. 비동기 워크의 경우 시드를 반드시 제공해야 합니다. 동기 워크를 수행할 때는 시드가 필요하지 않습니다.

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

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

설명

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

프로파일러에서는 스택 워크를 수행하려고 할 때 DoStackSnapshot을 호출합니다. CLR에서는 해당 호출로부터 반환되기 전에 스택의 관리되는 각 프레임(또는 관리되지 않는 프레임의 실행)에 대해 StackSnapshotCallback을 한 번씩 호출합니다. 관리되지 않는 프레임이 발견되면 사용자가 직접 스택 워크를 수행해야 합니다.

스택 워크 순서는 프레임이 스택에 푸시된 순서와 반대입니다. 즉, 마지막으로 푸시된 리프 프레임에서 첫 번째로 푸시된 주 프레임의 순서로 스택 워크가 수행됩니다.

관리되는 스택에 대해 스택 워크를 수행하도록 프로파일러를 프로그래밍하는 방법에 대한 자세한 내용은 MSDN Library에서 Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond를 참조하십시오.

다음 단원의 설명과 같이 스택 워크는 동기적이거나 비동기적일 수 있습니다.

동기 스택 워크

동기 스택 워크에는 콜백에 대한 응답으로 현재 스레드에서 수행되는 스택 워크가 포함됩니다. 시드나 일시 중단은 필요하지 않습니다.

CLR에서 프로파일러의 ICorProfilerCallback(또는 ICorProfilerCallback2) 메서드 중 하나를 호출해서 이에 대한 응답으로 DoStackSnapshot을 호출하여 현재 스레드에서 스택 워크를 수행할 때는 동기 호출을 수행합니다. ICorProfilerCallback::ObjectAllocated 등의 알림에서 스택이 어떻게 표시되는지 확인하려면 이 방법이 유용합니다. ICorProfilerCallback 메서드 내에서 DoStackSnapshot을 호출하고 context 및 thread 매개 변수에 null을 전달하기만 하면 됩니다.

비동기 스택 워크

비동기 스택 워크에는 다른 스레드 또는 현재 스레드에 대한 스택 워크가 포함됩니다. 비동기 스택 워크는 콜백에 대한 응답으로 수행되는 것이 아니라 현재 스레드의 명령 포인터를 도용함으로써 수행됩니다. 스택의 맨 위에 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를 호출하여 해당 대상 스레드의 스택을 워크합니다.

요구 사항

플랫폼: .NET Framework 시스템 요구 사항 참조

헤더: CorProf.idl, CorProf.h

라이브러리: CorGuids.lib

.NET Framework 버전: 4, 3.5 SP1, 3.5, 3.0 SP1, 3.0, 2.0 SP1, 2.0

참고 항목

참조

ICorProfilerInfo 인터페이스

ICorProfilerInfo2 인터페이스