확인된 빌드가 문제를 나타내는 방법

참고

확인된 빌드는 Windows 10 버전 1803 이전 버전의 Windows 사용할 수 있었습니다. 드라이버 검증 도구 및 GFlags와 같은 도구를 사용하여 이후 버전의 Windows 드라이버 코드를 확인합니다.

운영 체제의 확인된 빌드는 다양한 메서드를 사용하여 발견한 문제를 알립니다. 이러한 메서드에는 ASSERT 오류, 중단점 및 디버거 메시지가 포함됩니다. 이러한 모든 메서드는 커널 디버거에서 출력됩니다. 따라서 유용하려면 커널 모드 디버거(예: WinDbg 또는 KD)가 연결된 상태에서 확인된 빌드를 실행해야 합니다.

디버깅에 대한 자세한 내용은 Windows 디버깅을 참조하세요.

ASSERT 오류

확인된 빌드가 수행하는 대부분의 검사는 ASSERT 문으로 구현됩니다. 어설션된 식이 FALSE로 평가되면 디버거에 다음이 포함된 메시지가 표시됩니다.

  • 실패한 코드 식의 텍스트

  • 실패한 ASSERT 루틴의 소스 코드 경로, 파일 이름 및 줄 번호

다음 예제에서는 I/O 관리자에서 어설션이 실패할 때 디버거가 표시하는 출력을 보여 줍니다.

*** Assertion failed: Irp->IoStatus.Status != 0xffffffff
***   Source File: D:\nt\private\ntos\io\iosubs.c, line 3305

0:Break, Ignore, Terminate Process or Terminate Thread (bipt)? b
0:Execute '!cxr BD94B918' to dump context
Break instruction exception - code 80000003 (first chance)
ntkrnlmp!DbgBreakPoint:
804a3ce4 cc               int     3

디버거 출력에 표시된 것처럼 사용자에게 "스레드 중단, 무시, 프로세스 종료 또는 종료"라는 메시지가 표시됩니다. 사용자가 "b"를 입력하여 응답했습니다. 이로 인해 디버거가 중단점으로 시스템 실행을 중지했습니다. 따라서 이제 사용자는 검색된 문제를 계속 디버그할 수 있습니다.

실패한 어설션이 시스템에 영향을 미치는 방법은 여러 요인에 따라 달라집니다. Windows Vista 이전의 Windows 버전에서 시스템 시작 프로세스 중에 운영 체제에 대해 디버깅을 사용하도록 설정한 경우 시스템은 디버거에 침입하거나(연결된 경우) 디버거가 연결될 때까지 기다리지 않습니다. 디버깅을 사용하지 않으면 시스템에서 매개 변수 1 값 이 0x80000003 KMODE_EXCEPTION_NOT_HANDLED(Bug Check 0x1E)와 충돌합니다. Windows Vista 이상에서는 디버거가 연결된 경우에만 시스템이 디버거에 침입합니다. 디버깅을 사용하지 않거나 디버깅을 사용하도록 설정했지만 디버거가 연결되지 않은 경우 실패한 어설션은 보고되지 않습니다(어설션 검사는 계속 수행됨). 드라이버를 개발하고 디버깅을 사용하도록 설정했지만 디버거가 연결되지 않은 경우 디버거를 결정적으로 중단하려는 경우 코드에서 DbgBreakPoint 문을 사용할 수 있습니다.

일부 ASSERT 오류 앞에 추가 DbgPrint 출력이 있습니다. 이러한 유형의 어설션의 일반적인 예 중 하나는 다음 PAGED_CODE 매크로입니다. 이 매크로는 드라이버의 확인된 빌드에서 사용하기 위해 ntddk.h 및 wdm.h로 정의됩니다.

#define PAGED_CODE() \
    if (KeGetCurrentIrql() > APC_LEVEL) { \
KdPrint(( "EX: Pageable code called at IRQL %d\n", KeGetCurrentIrql() )); \
        ASSERT(FALSE); \
        }

이 매크로는 운영 체제 내에서 페이징 가능한 함수가 적절한 IRQL에서만 호출되는지 확인하는 데 자주 사용됩니다.

일반적으로 실패한 코드 식의 텍스트를 검사하여 ASSERT가 발생했을 때 드라이버의 작업과 호출된 함수를 포함하여 어설션의 원인을 확인할 수 있습니다. KB(스택 추적 표시) 디버거 명령은 이 분석에 매우 중요합니다.

가장 일반적인 ASSERT 호출 목록은 확인된 빌드 ASSERT를 참조하세요.

중단점

확인된 빌드는 중단점을 사용하여 문제를 나타낼 수도 있습니다. 중단점 앞에는 종종 DbgPrint 문이 있으며, 이로 인해 디버거가 발생한 문제에 대한 정보를 표시합니다. 중단점이 발생할 때 디버거가 시스템에 연결되지 않으면 시스템이 충돌하고 모든 설명 메시지가 손실됩니다.

확인된 빌드의 중단점 앞에 있고 드라이버 작성기에서 발생하는 가장 일반적인 메시지 중 일부는 확인된 빌드 중단점 및 메시지에 나열됩니다.

다음 예제에서는 디버거에 DbgPrint 호출 및 중단점이 표시되는 방법을 보여 냅니다.

*** DPC routine > 1 sec --- This is not a break in KeUpdateSystemTime
Break instruction exception - code 80000003 (first chance)
NTOSKRNL!DbgBreakPoint:
804a3ce4 cc               int     3

이 예제에서는 DPC(단일 지연 프로시저 호출)가 1초 이상 실행 중임을 나타내는 디버거 메시지를 보여 줍니다. 확인된 빌드에서 구현된 검사 유형을 보여 줍니다. 이 중단점은 드라이버가 DPC 루틴에서 오랜 시간을 보냈다는 것을 의미하며 이는 심각한 드라이버 문제를 나타낼 수 있습니다. 반면, 드라이버가 DPC 루틴에서 많은 양의 디버그 출력을 생성하여 DPC를 실행하는 데 필요한 시간을 연장하는 경우에도 이 중단점이 발생할 수 있습니다. 문제의 근본 원인을 검색하려면 DPC 루틴이 수행하는 작업을 검사하고 중단점을 한두 번 지나 계속합니다.

드물게 중단점이 발견되었지만 메시지가 표시되지 않는 경우 KB 디버거 명령을 사용하여 커널 스택 추적을 검사하여 중단점이 발생한 위치를 확인하는 것이 중요합니다. 종종 중단점에 대한 이유에 대한 강력한 단서를 제공합니다.

다음 예제에서는 스택 추적과 함께 많은 Windows 드라이버 개발자가 볼 수 있는 일반적인 중단점을 보여 줍니다.

Break instruction exception - code 80000003 (first chance)
ntkrnlmp!SpinLockSpinningForTooLong:
8069aafd cc               int     3
1: kd> kb
ChildEBP RetAddr  Args to Child              
f9f77c4c 80103a6c f9f77c84 00000005 fa20e7df ntkrnlmp!SpinLockSpinningForTooLong
f9f77c58 fa20e7df 81b34930 e1558bd0 00180016 halmps!KfAcquireSpinLock+0x3c
f9f77c7c 80742683 000000ff 81ba6000 00000000 nothing+0x7df
f9f77d54 80742893 0000046c 81ba6000 f9f77d80 ntkrnlmp!IopLoadDriver+0x785
f9f77d78 805f8d2d 00000000 00000000 81fa88b8 ntkrnlmp!IopLoadUnloadDriver+0x75
f9f77dac 807cd14f f7d59ce8 00000000 00000000 ntkrnlmp!ExpWorkerThread+0x129
f9f77ddc 8069bece 805f8c04 00000001 00000000 ntkrnlmp!PspSystemThreadStartup+0x4d
00000000 00000000 00000000 00000000 00000000 ntkrnlmp!KiThreadStartup+0x16

이 스택 추적에서 볼 수 있듯이 중단점은 KfAcquireSpinLock 호출의 결과로 수행되었습니다. wdm.h를 검사한 후 드라이버에서 KeAcquireSpinLock이라고 하는 함수의 실제 이름임을 확인할 수 있습니다. 중단점 이전에 메시지가 표시되지 않았더라도 스택 맨 위에 있는 중단점의 위치를 볼 수 있습니다(ntkrnlmp! SpinLockSpinningForTooLong). 이 위치는 중단점에 대한 이유를 나타냅니다. 스핀 잠금이 비정상적으로 오랜 시간 동안 회전하여 획득이 보류되었습니다.

디버거 메시지

확인된 빌드는 디버거 메시지를 사용하여 발생한 오류를 식별하거나 추가 정보를 제공할 수도 있습니다. 디버거 메시지의 가장 일반적인 원본은 커널이 아닌 구성 요소와 HAL이 아닌 구성 요소 또는 확인된(디버그) 사용자 모드 프로그램에서 발생하는 오류입니다. 출력 양은 운영 체제 릴리스마다 다릅니다.

다음 예제에서는 전체 확인된 빌드를 설치하여 표시할 수 있는 출력을 보여 주는 예제입니다. 이 출력은 시험판 버전의 Windows XP에서 생성되었으므로 완전히 확인된 빌드에서 일반적으로 볼 수 있는 것보다 훨씬 볼륨이 높습니다.

0:Attempting to load winsock
0:Checking for presence of ws2_32
0:Looking in ws2_32 for getaddrinfo
0:AudioSrv: 1:CreateSessionUserSid: GetCurrentUserTokenW failed, LastError=1245
1:AudioSrv: RegOpenConsoleUser: no console sid
0:(s: 0 0xc4.d0 winlogon.exe) USRK-[Wrn=170] CloseDesktop: Desktop 0X81CEAF78 still in use by thread 0XE16F3EA0
0:GetWinStationUserToken: Error 1702 getting UserToken LogonId 0
1:AudioSrv: InitializeForNewConsoleUser: User SID S-1-5-21-329068152-1292428093-1547161642-500
1:(s: 0 0x240.3a8 spoolsv.exe) USRK-[Wrn=1400] ValidateHwnd: Invalid hwnd (0X0000FFFF)
0:(s: 0 0x240.3a8 spoolsv.exe) USRK-[Wrn=1400] ValidateHwnd: Invalid hwnd (0X0000FFFF)
0:bReadUserSystemEUDCRegistry():fail NtStatus - c0000000
0:GDI: GDISRV:Fail to read system wide eudc
0:
1:TERMSRV : Not Personal Workstation
0:(s: 0 0x260.3c4 Explorer.EXE) USER-[Wrn=1400] HMValidateHandle: Invalid:00000000 Type:0x1
0:(s: 0 0x260.3c4 Explorer.EXE) USER-[Wrn=1400] HMValidateHandle: Invalid:00000000 Type:0x1
0:(s: 0 0x260.3c4 Explorer.EXE) USER-[Wrn=1400] HMValidateHandle: Invalid:00000000 Type:0x1

드라이버 디버깅 중에 확인된 빌드가 표시할 수 있는 가장 일반적인 메시지 중 일부는 확인된 빌드 중단점 및 메시지에 나열됩니다.

다양한 시스템 구성 요소에서 추가 추적 또는 정보 메시지를 사용하도록 설정하면 후속 중단점이나 ASSERT 오류 없이 디버거 메시지가 발생할 수도 있습니다.