使用 !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 (Display Exception Record) 命令來 檢視此資訊。

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] 欄位會顯示堆疊上的最後一個呼叫。 在此情況下,位址0x01050963的程式代碼0x77F97704呼叫函式。 您可以使用這些位址搭配 ln (List Nearest Symbols) 命令來判斷這些位址所在的模組和函式。

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.

顯示的第一個項目會顯示錯誤檢查程序代碼,以及此類型錯誤檢查的相關信息。 某些顯示的文字可能不適用於這個特定實例。 如需每個錯誤檢查的詳細資訊,請參閱 錯誤檢查程式代碼參考 一節。

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欄位。 這些只是重新設定錯誤檢查參數中顯示的資訊。 藉由比較語句 「非分頁集區」與錯誤檢查文字,讀取「嘗試存取可分頁 (或完全無效的) 位址」,我們可以看到位址無效。 在此案例中,無效的位址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 (Display Trap Frame) 命令來檢視此資訊。

LAST_CONTROL_TRANSFER:  from f83206e0 to f832035c

[LAST_CONTROL_TRANSFER] 欄位會顯示堆疊上的最後一個呼叫。 在此情況下,位址0xF83206E0的程式代碼0xF832035C呼叫函式。 您可以使用 ln (List Nearest Symbols) 命令來判斷這些位址所在的模組和函式。

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 來判斷問題的原因。

另請參閱

如需詳細資訊,請參閱這些主題。

!分析

錯誤檢查代碼參考

使用 Windows 調試程式進行損毀傾印分析 (WinDbg)

使用 WinDbg 分析 Kernel-Mode 傾印檔案