Uso dell'estensione !analyze
Il primo passaggio per eseguire il debug di un computer o un'applicazione di destinazione arrestata in modo anomalo consiste nell'usare il comando di estensione !analyze . Questa estensione esegue una grande quantità di analisi automatizzate. I risultati di questa analisi vengono visualizzati nella finestra Comando debugger.
È consigliabile usare l'opzione -v per una visualizzazione completa dei dati. Per informazioni dettagliate su altre opzioni, vedere la pagina di riferimento !analyze .
Un esempio di utente in modalità utente !analyze -v
In questo esempio il debugger viene collegato a un'applicazione in modalità utente che ha rilevato un'eccezione.
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
Debugger SolutionDb Connection::Open failed 80004005
Se si è connessi a Internet, il debugger tenta di accedere a un database di soluzioni di arresto anomalo gestite da Microsoft. In questo caso è stato visualizzato un messaggio di errore che indica che il computer non è riuscito ad accedere a Internet o che il sito Web non funziona.
FAULTING_IP:
ntdll!PropertyLengthAsVariant+73
77f97704 cc int 3
Il campo FAULTING_IP mostra il puntatore all'istruzione al momento dell'errore.
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
Il campo EXCEPTION_RECORD mostra il record di eccezione per questo arresto anomalo. Queste informazioni possono essere visualizzate anche usando il comando .exr (Display Exception Record).
BUGCHECK_STR: 80000003
Il campo BUGCHECK_STR mostra il codice eccezione. Il nome è un errore: il termine controllo dei bug indica effettivamente un arresto anomalo della modalità kernel. Nel debug in modalità utente, verrà visualizzato il codice di eccezione, in questo caso 0x80000003.
DEFAULT_BUCKET_ID: APPLICATION_FAULT
Il campo DEFAULT_BUCKET_ID mostra la categoria generale di errori a cui appartiene questo errore.
PROCESS_NAME: MyApp.exe
Il campo PROCESS_NAME specifica il nome del processo che ha generato l'eccezione.
LAST_CONTROL_TRANSFER: from 01050963 to 77f97704
Il campo LAST_CONTROL_TRANSFER mostra l'ultima chiamata nello stack. In questo caso, il codice all'indirizzo 0x01050963 chiamato funzione in 0x77F97704. È possibile usare questi indirizzi con il comando ln (List Nearest Symbols) per determinare quali moduli e funzioni si trovano in questi indirizzi.
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
Il campo STACK_TEXT mostra un'analisi dello stack del componente di errore.
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
Quando !analyze determina l'istruzione che ha probabilmente causato l'errore, la visualizza nel campo FOLLOWUP_IP. I campi SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DEBUG_FLR_IMAGE_TIMESTAMP mostrano il simbolo, il modulo, il nome dell'immagine e il timestamp dell'immagine corrispondenti a questa istruzione.
STACK_COMMAND: .ecxr ; kb
Il campo STACK_COMMAND mostra il comando usato per ottenere il STACK_TEXT. È possibile usare questo comando per ripetere la visualizzazione dell'analisi dello stack o modificarla per ottenere informazioni sullo stack correlate.
BUCKET_ID: 80000003_MyApp!FatalErrorBox+55
Il campo BUCKET_ID mostra la categoria specifica di errori a cui appartiene l'errore corrente. Questa categoria consente al debugger di determinare quali altre informazioni visualizzare nell'output di analisi.
Followup: dbg
---------
Per informazioni sui campi FOLLOWUP_NAME e Followup, vedere Il campo di completamento e il file triage.ini.
Esistono diversi altri campi che possono essere visualizzati:
Se il controllo è stato trasferito a un indirizzo non valido, il campo FAULTING_IP conterrà questo indirizzo non valido. Invece del campo FOLLOWUP_IP, il campo FAILED_INSTRUCTION_ADDRESS mostrerà il codice disassemblato da questo indirizzo, anche se questo disassembly sarà probabilmente privo di significato. In questo caso, i campi SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DEBUG_FLR_IMAGE_TIMESTAMP fanno riferimento al chiamante di questa istruzione.
Se il processore non viene generato, è possibile che vengano visualizzati i campi SINGLE_BIT_ERROR, TWO_BIT_ERROR o POSSIBLE_INVALID_CONTROL_TRANSFER.
Se si è verificato un danneggiamento della memoria, il campo CHKIMG_EXTENSION specifica il comando di estensione !chkimg da usare per analizzare.
Un esempio di kernel !analyze -v
In questo esempio il debugger viene collegato a un computer che è appena stato arrestato in modo anomalo.
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.
Il primo elemento della visualizzazione mostra il codice di controllo dei bug e le informazioni su questo tipo di controllo dei bug. Alcuni del testo visualizzato potrebbero non essere applicabili a questa istanza specifica. Per altri dettagli su ogni controllo dei bug, vedere la sezione Riferimento al codice di controllo dei bug.
Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory
I parametri di controllo dei bug vengono visualizzati successivamente. Ognuno di essi è seguito da una descrizione. Ad esempio, il terzo parametro è 1 e il commento seguente spiega che indica che un'operazione di scrittura non è riuscita.
## Debugging Details:
WRITE_ADDRESS: 00000004 Nonpaged pool
CURRENT_IRQL: 2
I campi successivi variano a seconda della natura dell'arresto anomalo. In questo caso vengono visualizzati WRITE_ADDRESS e CURRENT_IRQL campi. Si tratta semplicemente di riformulare le informazioni visualizzate nei parametri di controllo dei bug. Confrontando l'istruzione "Nonpaged pool" con il testo di controllo dei bug che legge "è stato effettuato un tentativo di accesso a un indirizzo pagable (o completamente non valido), è possibile notare che l'indirizzo non è valido. L'indirizzo non valido in questo caso è stato 0x00000004.
FAULTING_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
Il campo FAULTING_IP mostra il puntatore all'istruzione al momento dell'errore.
DEFAULT_BUCKET_ID: DRIVER_FAULT
Il campo DEFAULT_BUCKET_ID mostra la categoria generale di errori a cui appartiene questo errore.
BUGCHECK_STR: 0xD1
Il campo BUGCHECK_STR mostra il codice di controllo dei bug, già visto. In alcuni casi vengono aggiunte ulteriori informazioni di valutazione.
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
Il campo TRAP_FRAME mostra il fotogramma trap per questo arresto anomalo. Queste informazioni possono essere visualizzate anche usando il comando trap (Display Trap Frame).
LAST_CONTROL_TRANSFER: from f83206e0 to f832035c
Il campo LAST_CONTROL_TRANSFER mostra l'ultima chiamata nello stack. In questo caso, il codice in corrispondenza dell'indirizzo 0xF83206E0 chiamato funzione in 0xF832035C. È possibile usare il comando ln (List Nearest Symbols) per determinare il modulo e la funzione in cui si trovano questi indirizzi.
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
Il campo STACK_TEXT mostra un'analisi dello stack del componente di errore.
FOLLOWUP_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
Il campo FOLLOWUP_IP mostra il disassembly dell'istruzione che probabilmente ha causato l'errore.
FOLLOWUP_NAME: usbtri
SYMBOL_NAME: USBPORT!USBPORT_BadRequestFlush+7c
MODULE_NAME: USBPORT
IMAGE_NAME: USBPORT.SYS
DEBUG_FLR_IMAGE_TIMESTAMP: 3b7d868b
I campi SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP mostrano il timestamp simbolo, modulo, immagine e immagine corrispondente a questa istruzione (se è valido) o al chiamante di questa istruzione (in caso contrario).
STACK_COMMAND: .trap fffffffff8950dfc ; kb
Il campo STACK_COMMAND mostra il comando usato per ottenere il STACK_TEXT. È possibile usare questo comando per ripetere la visualizzazione dell'analisi dello stack o modificarla per ottenere informazioni sullo stack correlate.
BUCKET_ID: 0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c
Il campo BUCKET_ID mostra la categoria specifica di errori a cui appartiene l'errore corrente. Questa categoria consente al debugger di determinare quali altre informazioni visualizzare nell'output di analisi.
Per informazioni sui campi FOLLOWUP_NAME e Followup, vedere Il campo di completamento e il file triage.ini.
Esistono diversi altri campi che possono essere visualizzati:
Se il controllo è stato trasferito a un indirizzo non valido, il campo FAULTING_IP conterrà questo indirizzo non valido. Invece del campo FOLLOWUP_IP, il campo FAILED_INSTRUCTION_ADDRESS mostrerà il codice disassemblato da questo indirizzo, anche se questo disassembly sarà probabilmente privo di significato. In questo caso, i campi SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP fanno riferimento al chiamante di questa istruzione.
Se il processore non viene generato, è possibile che vengano visualizzati i campi SINGLE_BIT_ERROR, TWO_BIT_ERROR o POSSIBLE_INVALID_CONTROL_TRANSFER.
Se si è verificato un danneggiamento della memoria, il campo CHKIMG_EXTENSION specifica il comando di estensione !chkimg da usare per analizzare.
Se si è verificato un controllo dei bug all'interno del codice di un driver di dispositivo, il relativo nome può essere visualizzato nel campo BUGCHECKING_DRIVER.
Campo di completamento e file triage.ini
Sia in modalità utente che in modalità kernel, il campo Followup nella visualizzazione mostrerà informazioni sul proprietario del frame dello stack corrente, se possibile. Queste informazioni vengono determinate nel modo seguente:
Quando si usa l'estensione !analyze , il debugger inizia con il frame superiore nello stack e determina se è responsabile dell'errore. In caso contrario, viene analizzato il fotogramma successivo. Questo processo continua fino a quando non viene trovato un frame che potrebbe essere in errore.
Il debugger tenta di determinare il proprietario del modulo e della funzione in questo frame. Se il proprietario può essere determinato, questo frame viene considerato in errore.
Se il proprietario non può essere determinato, il debugger passa al frame dello stack successivo e così via, fino a quando il proprietario non viene determinato (o lo stack non viene esaminato completamente). Il primo frame il cui proprietario viene trovato in questa ricerca è considerato in errore. Se lo stack viene esaurito senza alcuna informazione trovata, non viene visualizzato alcun campo Followup.
Il proprietario del frame in caso di errore viene visualizzato nel campo Followup. Se si usa !analyze -v , i campi FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP faranno riferimento a questo frame.
Per visualizzare informazioni utili, è necessario innanzitutto creare un file triage.ini contenente i nomi del modulo e dei proprietari delle funzioni.
Il file triage.ini deve identificare i proprietari di tutti i moduli che potrebbero avere errori. È possibile usare una stringa informativa anziché un proprietario effettivo, ma questa stringa non può contenere spazi. Se si è certi che un modulo non avrà esito positivo, è possibile omettere questo modulo o indicare che deve essere ignorato. È anche possibile specificare proprietari di singole funzioni, fornendo al processo di valutazione una granularità ancora più fine.
Per informazioni dettagliate sulla sintassi del file triage.ini, vedere Specifica dei proprietari di moduli e funzioni.
Altre tecniche !analyze
Se non si è verificato alcun arresto anomalo o eccezione, !analyze visualizzerà un testo molto breve che indica lo stato corrente della destinazione. In determinate situazioni può essere necessario forzare l'analisi come se si fosse verificato un arresto anomalo. Usare !analyze -f per eseguire questa attività.
In modalità utente, se si è verificata un'eccezione, ma si ritiene che il problema sottostante sia un thread bloccato, impostare il thread corrente sul thread che si sta analizzando e quindi usare !analyze -hang. Questa estensione eseguirà un'analisi dello stack di thread per determinare se eventuali thread bloccano altri thread.
In modalità kernel, se si è verificato un controllo dei bug, ma si ritiene che il problema sottostante sia un thread bloccato, usare !analyze -hang. Questa estensione analizzerà i blocchi mantenuti dal sistema e analizzerà la catena di code DPC e visualizzerà eventuali indicazioni di thread bloccati. Se si ritiene che il problema sia un deadlock delle risorse in modalità kernel, usare l'estensione !deadlock insieme all'opzione Rilevamento deadlock di Driver Verifier.
È anche possibile ignorare automaticamente i problemi noti. A tale scopo, è prima necessario creare un file XML contenente un elenco formattato di problemi noti. Usare l'estensione !analyze -c -load KnownIssuesFile per caricare il file. Quindi, quando si verifica un'eccezione o un'interruzione, usare l'estensione !analyze -c . Se l'eccezione corrisponde a uno dei problemi noti, la destinazione riprenderà l'esecuzione. Se la destinazione non riprende l'esecuzione, è possibile usare !analyze -v per determinare la causa del problema.
Vedi anche
Per altre informazioni, vedere questi argomenti.
Riferimento al codice del controllo errori
Analisi del dump di arresto anomalo del sistema usando i debugger di Windows (WinDbg)