!analyze 확장 사용

충돌한 대상 컴퓨터 또는 애플리케이션을 디버깅하는 첫 번째 단계는 !analyze 확장 명령을 사용하는 것입니다. 이 확장은 대량의 자동화된 분석을 수행합니다. 이 분석의 결과는 디버거 명령 창에 표시됩니다.

데이터의 전체 세부 정보 표시에 -v 옵션을 사용해야 합니다. 다른 옵션에 대한 자세한 내용은 !analyze 참조 페이지를 참조하세요.

User-Mode !analyze -v 예제

이 예제에서 디버거는 예외가 발생한 사용자 모드 애플리케이션에 연결됩니다.

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Debugger SolutionDb Connection::Open failed 80004005

인터넷에 연결된 경우 디버거는 Microsoft에서 유지 관리하는 크래시 솔루션의 데이터베이스에 액세스하려고 시도합니다. 이 경우 컴퓨터가 인터넷에 액세스할 수 없거나 웹 사이트가 작동하지 않음을 나타내는 오류 메시지가 표시되었습니다.

FAULTING_IP: 
ntdll!PropertyLengthAsVariant+73
77f97704 cc               int     3

FAULTING_IP 필드는 오류 발생 시 명령 포인터를 표시합니다.

EXCEPTION_RECORD:  ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 00010101
   Parameter[2]: ffffffff

EXCEPTION_RECORD 필드에는 이 크래시에 대한 예외 레코드가 표시됩니다. 이 정보는 .exr(표시 예외 레코드) 명령을 사용하여 볼 수도 있습니다.

BUGCHECK_STR:  80000003

BUGCHECK_STR 필드에 예외 코드가 표시됩니다. 이름은 잘못된 이름입니다. 버그 검사 용어는 실제로 커널 모드 충돌을 나타냅니다. 사용자 모드 디버깅에서는 예외 코드가 표시됩니다.이 경우 0x80000003.

DEFAULT_BUCKET_ID:  APPLICATION_FAULT

DEFAULT_BUCKET_ID 필드는 이 오류가 속한 일반적인 실패 범주를 보여 줍니다.

PROCESS_NAME:  MyApp.exe

PROCESS_NAME 필드는 예외를 발생시킨 프로세스의 이름을 지정합니다.

LAST_CONTROL_TRANSFER:  from 01050963 to 77f97704

LAST_CONTROL_TRANSFER 필드에 스택의 마지막 호출이 표시됩니다. 이 경우 주소의 코드는 0x77F97704 함수라고 0x01050963. ln(가장 가까운 기호 나열) 명령과 함께 이러한 주소를 사용하여 이러한 주소가 상주하는 모듈 및 함수를 확인할 수 있습니다.

STACK_TEXT:  
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d

STACK_TEXT 필드에는 오류 구성 요소의 스택 추적이 표시됩니다.

FOLLOWUP_IP: 
MyApp!FatalErrorBox+55
01050963 5e               pop     esi

FOLLOWUP_NAME:  dbg

SYMBOL_NAME:  MyApp!FatalErrorBox+55

MODULE_NAME:  MyApp

IMAGE_NAME:  MyApp.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  383490a9

!analyze에서 오류를 발생시킨 명령이 결정되면 FOLLOWUP_IP 필드에 표시됩니다. SYMBOL_NAME, MODULE_NAME, IMAGE_NAME 및 DEBUG_FLR_IMAGE_TIMESTAMP 필드에는 이 명령에 해당하는 기호, 모듈, 이미지 이름 및 이미지 타임스탬프가 표시됩니다.

STACK_COMMAND:  .ecxr ; kb

STACK_COMMAND 필드에는 STACK_TEXT 가져오는 데 사용된 명령이 표시됩니다. 이 명령을 사용하여 이 스택 추적 표시를 반복하거나 변경하여 관련 스택 정보를 가져올 수 있습니다.

BUCKET_ID:  80000003_MyApp!FatalErrorBox+55

BUCKET_ID 필드는 현재 오류가 속한 특정 실패 범주를 보여 줍니다. 이 범주는 디버거가 분석 출력에 표시할 다른 정보를 결정하는 데 도움이 됩니다.

Followup: dbg
---------

FOLLOWUP_NAME 및 후속 필드에 대한 자세한 내용은 후속 필드 및 triage.ini 파일을 참조하세요.

다음과 같은 다양한 필드가 나타날 수 있습니다.

  • 컨트롤이 잘못된 주소로 전송된 경우 FAULTING_IP 필드에 이 잘못된 주소가 포함됩니다. FOLLOWUP_IP 필드 대신 FAILED_INSTRUCTION_ADDRESS 필드에는 이 주소의 디스어셈블된 코드가 표시되지만 이 디스어셈블리는 의미가 없을 수 있습니다. 이 경우 SYMBOL_NAME, MODULE_NAME, IMAGE_NAME 및 DEBUG_FLR_IMAGE_TIMESTAMP 필드는 이 명령의 호출자를 참조합니다.

  • 프로세서가 실화되면 SINGLE_BIT_ERROR, TWO_BIT_ERROR 또는 POSSIBLE_INVALID_CONTROL_TRANSFER 필드가 표시 될 수 있습니다.

  • 메모리 손상이 발생한 것으로 보이는 경우 CHKIMG_EXTENSION 필드에 조사에 사용해야 하는 !chkimg 확장 명령이 지정됩니다.

Kernel-Mode !analyze -v 예제

이 예제에서는 디버거가 방금 충돌한 컴퓨터에 연결됩니다.

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.

디스플레이의 첫 번째 요소는 버그 검사 코드와 이러한 유형의 버그 검사 대한 정보를 표시합니다. 표시되는 텍스트 중 일부는 이 특정 instance 적용되지 않을 수 있습니다. 각 버그 검사 대한 자세한 내용은 버그 검사 코드 참조 섹션을 참조하세요.

Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory

버그 검사 매개 변수는 다음에 표시됩니다. 각각 설명이 뒤에 잇습니다. 예를 들어 세 번째 매개 변수는 1이고 다음 주석은 쓰기 작업이 실패했음을 나타냅니다.

## Debugging Details:


WRITE_ADDRESS:  00000004 Nonpaged pool

CURRENT_IRQL:  2

다음 몇 필드는 충돌의 특성에 따라 달라집니다. 이 경우 WRITE_ADDRESS 및 CURRENT_IRQL 필드가 표시됩니다. 이는 단순히 버그 검사 매개 변수에 표시된 정보를 다시 설명합니다. "Nonpaged pool"이라는 문을 버그 검사 텍스트와 비교하여 "페이지가 매긴(또는 완전히 잘못된) 주소에 액세스하려고 했습니다."라는 텍스트를 비교하면 주소가 유효하지 않은 것을 확인할 수 있습니다. 이 경우 잘못된 주소가 0x00000004.

FAULTING_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FAULTING_IP 필드는 오류 발생 시 명령 포인터를 표시합니다.

DEFAULT_BUCKET_ID:  DRIVER_FAULT

DEFAULT_BUCKET_ID 필드는 이 오류가 속한 일반적인 실패 범주를 보여 줍니다.

BUGCHECK_STR:  0xD1

BUGCHECK_STR 필드에는 이미 본 버그 검사 코드가 표시됩니다. 경우에 따라 추가 심사 정보가 추가됩니다.

TRAP_FRAME:  f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0         nv up ei pl nz ac po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204           mov     [edx+0x4],eax     ds:0023:00000004=????????
.trap
Resetting default context

TRAP_FRAME 필드에는 이 크래시에 대한 트랩 프레임이 표시됩니다. .trap(트랩 프레임 표시) 명령을 사용하여 이 정보를 볼 수도 있습니다.

LAST_CONTROL_TRANSFER:  from f83206e0 to f832035c

LAST_CONTROL_TRANSFER 필드에 스택의 마지막 호출이 표시됩니다. 이 경우 주소의 코드는 0xF832035C 함수라고 0xF83206E0. ln(가장 가까운 기호 나열) 명령을 사용하여 이러한 주소가 상주하는 모듈 및 함수를 확인할 수 있습니다.

STACK_TEXT:  
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31

STACK_TEXT 필드에는 오류 구성 요소의 스택 추적이 표시됩니다.

FOLLOWUP_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FOLLOWUP_IP 필드에는 오류를 발생시킨 명령의 디스어셈블리가 표시됩니다.

FOLLOWUP_NAME:  usbtri

SYMBOL_NAME:  USBPORT!USBPORT_BadRequestFlush+7c

MODULE_NAME:  USBPORT

IMAGE_NAME:  USBPORT.SYS

DEBUG_FLR_IMAGE_TIMESTAMP:  3b7d868b

SYMBOL_NAME, MODULE_NAME, IMAGE_NAME 및 DBG_FLR_IMAGE_TIMESTAMP 필드에는 이 명령(유효한 경우)에 해당하는 기호, 모듈, 이미지 및 이미지 타임스탬프 또는 이 명령의 호출자(그렇지 않은 경우)가 표시됩니다.

STACK_COMMAND:  .trap fffffffff8950dfc ; kb

STACK_COMMAND 필드에는 STACK_TEXT 가져오는 데 사용된 명령이 표시됩니다. 이 명령을 사용하여 이 스택 추적 표시를 반복하거나 변경하여 관련 스택 정보를 가져올 수 있습니다.

BUCKET_ID:  0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c

BUCKET_ID 필드는 현재 오류가 속한 특정 실패 범주를 보여 줍니다. 이 범주는 디버거가 분석 출력에 표시할 다른 정보를 결정하는 데 도움이 됩니다.

FOLLOWUP_NAME 및 후속 필드에 대한 자세한 내용은 후속 필드 및 triage.ini 파일을 참조하세요.

다음과 같은 다양한 필드가 나타날 수 있습니다.

  • 컨트롤이 잘못된 주소로 전송된 경우 FAULTING_IP 필드에 이 잘못된 주소가 포함됩니다. FOLLOWUP_IP 필드 대신 FAILED_INSTRUCTION_ADDRESS 필드에는 이 주소의 디스어셈블된 코드가 표시되지만 이 디스어셈블리는 의미가 없을 수 있습니다. 이 경우 SYMBOL_NAME, MODULE_NAME, IMAGE_NAME 및 DBG_FLR_IMAGE_TIMESTAMP 필드는 이 명령의 호출자를 참조합니다.

  • 프로세서가 실화되면 SINGLE_BIT_ERROR, TWO_BIT_ERROR 또는 POSSIBLE_INVALID_CONTROL_TRANSFER 필드가 표시 될 수 있습니다.

  • 메모리 손상이 발생한 것으로 보이는 경우 CHKIMG_EXTENSION 필드에 조사에 사용해야 하는 !chkimg 확장 명령이 지정됩니다.

  • 디바이스 드라이버의 코드 내에서 버그 검사 발생한 경우 해당 이름이 BUGCHECKING_DRIVER 필드에 표시될 수 있습니다.

후속 필드 및 triage.ini 파일

사용자 모드와 커널 모드 모두에서 표시의 후속 필드에는 현재 스택 프레임의 소유자에 대한 정보가 표시됩니다(확인할 수 있는 경우). 이 정보는 다음과 같은 방식으로 결정됩니다.

  1. !analyze 확장을 사용하면 디버거가 스택의 위쪽 프레임으로 시작하여 오류의 책임이 있는지 여부를 결정합니다. 그렇지 않으면 다음 프레임이 분석됩니다. 이 프로세스는 오류가 있을 수 있는 프레임이 발견될 때까지 계속됩니다.

  2. 디버거는 이 프레임에서 모듈 및 함수의 소유자를 확인하려고 시도합니다. 소유자를 확인할 수 있는 경우 이 프레임은 오류로 간주됩니다.

  3. 소유자를 확인할 수 없는 경우 디버거는 소유자가 결정될 때까지(또는 스택이 완전히 검사될 때까지) 다음 스택 프레임으로 전달됩니다. 이 검색에서 소유자가 발견된 첫 번째 프레임은 오류로 간주됩니다. 정보를 찾지 못한 채 스택이 소진되면 후속 필드가 표시되지 않습니다.

  4. 오류에 있는 프레임의 소유자가 후속 필드에 표시됩니다. !analyze -v를 사용하는 경우 FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME 및 DBG_FLR_IMAGE_TIMESTAMP 필드가 이 프레임을 참조합니다.

후속 필드에 유용한 정보를 표시하려면 먼저 모듈 및 함수 소유자의 이름이 포함된 triage.ini 파일을 만들어야 합니다.

triage.ini 파일은 오류가 발생할 수 있는 모든 모듈의 소유자를 식별해야 합니다. 실제 소유자 대신 정보 문자열을 사용할 수 있지만 이 문자열에는 공백이 포함될 수 없습니다. 모듈에 오류가 없다고 확신하는 경우 이 모듈을 생략하거나 건너뛰어야 함을 나타낼 수 있습니다. 또한 개별 함수의 소유자를 지정하여 심사 프로세스를 더욱 세분화할 수 있습니다.

triage.ini 파일의 구문에 대한 자세한 내용은 모듈 및 함수 소유자 지정을 참조하세요.

추가 !analyze 기술

크래시 또는 예외가 발생하지 않은 경우 !analyze는 대상의 현재 상태 제공하는 매우 짧은 텍스트를 표시합니다. 특정 상황에서는 충돌이 발생한 것처럼 분석을 강제로 수행할 수 있습니다. !analyze -f를 사용하여 이 작업을 수행합니다.

사용자 모드에서 예외가 발생했지만 기본 문제가 중단된 스레드라고 생각되는 경우 현재 스레드를 조사 중인 스레드로 설정한 다음 !analyze -hang을 사용합니다. 이 확장은 스레드 스택 분석을 수행하여 스레드가 다른 스레드를 차단하는지 확인합니다.

커널 모드에서 버그 검사 발생했지만 기본 문제가 중단된 스레드라고 생각되는 경우 !analyze -hang을 사용합니다. 이 확장은 시스템에서 보유한 잠금을 조사하고 DPC 큐 체인을 검사하며 중단된 스레드의 표시를 표시합니다. 문제가 커널 모드 리소스 교착 상태라고 생각되면 드라이버 검증 도구의 교착 상태 검색 옵션과 함께 !deadlock 확장을 사용합니다.

알려진 문제를 자동으로 무시할 수도 있습니다. 이렇게 하려면 먼저 알려진 문제의 서식이 지정된 목록을 포함하는 XML 파일을 만들어야 합니다. !analyze -c -loadKnownIssuesFile 확장자를 사용하여 이 파일을 로드합니다. 그런 다음 예외 또는 중단이 발생하면 !analyze -c 확장을 사용합니다. 예외가 알려진 문제 중 하나와 일치하는 경우 대상은 실행을 다시 시작합니다. 대상이 실행을 다시 시작하지 않으면 !analyze -v 를 사용하여 문제의 원인을 확인할 수 있습니다.

추가 정보

자세한 내용은 다음 topics 참조하세요.

!분석

오류 검사 코드 참조

Windows 디버거를 사용한 크래시 덤프 분석(WinDbg)

WinDbg를 사용하여 Kernel-Mode 덤프 파일 분석