開始使用 WinDbg (使用者模式)

WinDbg 是 Windows 偵錯工具中包含的內核模式和使用者模式調試程式。 下列實際操作練習可協助您開始使用 WinDbg 作為使用者模式調試程式。

如需如何取得 Windows 偵錯工具的詳細資訊,請參閱 下載並安裝 WinDbg Windows 調試程式

安裝偵錯工具之後,請尋找 64 位 (x64) 和 32 位 (x86) 版本的工具安裝目錄。 例如:

  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x86

開啟 記事本 並附加 WinDbg

  1. 移至您的安裝目錄,然後開啟 WinDbg.exe

  2. 在 [ 檔案] 選單上,選取 [ 啟動可執行檔]。 在 [啟動可執行檔] 對話框中,移至包含notepad.exe的資料夾。 (notepad.exe檔案通常位於 C:\Windows\System32 中。針對 [ 檔名],輸入 notepad.exe。 選取開啟

    Screenshot of WinDbg with Notepad open.

  3. 在 WinDbg 視窗底部附近的命令列中,輸入下列命令:

    .sympath srv*

    輸出類似於下列範例:

    Symbol search path is: srv*
    Expanded Symbol search path is: cache*;SRV
    

    符號搜尋路徑會告知 WinDbg 要在哪裡尋找符號 (PDB) 檔案。 調試程式需要符號檔,才能取得程式代碼模組的相關信息,例如函式名稱和變數名稱。

    然後,輸入此命令:

    。重新載入

    命令 .reload 會告訴 WinDbg 進行初始搜尋,以尋找並載入符號檔。

  4. 若要查看notepad.exe模組的符號,請輸入下列命令:

    x 記事本!*

    注意

    如果沒有出現輸出,請輸入 .reload /f 以嘗試強制載入符號。 使用 !sym 嘈雜來顯示其他符號載入資訊。

    若要查看包含 的 notepad.exe 模組 main中的符號,請使用 檢查符號 命令來列出符合遮罩的模組:

    x notepad!wWin*

    輸出類似於下列範例:

    00007ff6`6e76b0a0 notepad!wWinMain (wWinMain)
    00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
    
  5. 若要將斷點 notepad!wWinMain放在 ,請輸入下列命令:

    bu 記事本!wWinMain

    若要確認已設定斷點,請輸入下列命令:

    bl

    輸出類似於下列範例:

    0 e Disable Clear  00007ff6`6e76b0a0     0001 (0001)  0:**** notepad!wWinMain
    
  6. 若要啟動 記事本 程式,請輸入下列命令:

    g

    記事本 會執行,直到它進入函WinMain式為止,然後將它中斷至調試程式。

    Breakpoint 0 hit
    notepad!wWinMain:
    00007ff6`6e76b0a0 488bc4          mov     rax,rsp
    

    若要查看目前在 記事本 程式中載入的程式代碼模組清單,請輸入下列命令:

    lm

    輸出類似於下列範例:

    0:000> lm
    start             end                 module name
    00007ff6`6e760000 00007ff6`6e798000   notepad    (pdb symbols)          C:\ProgramData\Dbg\sym\notepad.pdb\BC04D9A431EDE299D4625AD6201C8A4A1\notepad.pdb
    00007ff8`066a0000 00007ff8`067ab000   gdi32full   (deferred)             
    00007ff8`067b0000 00007ff8`068b0000   ucrtbase   (deferred)             
    00007ff8`06a10000 00007ff8`06aad000   msvcp_win   (deferred)             
    00007ff8`06ab0000 00007ff8`06ad2000   win32u     (deferred)             
    00007ff8`06b40000 00007ff8`06e08000   KERNELBASE   (deferred)             
    00007ff8`07220000 00007ff8`072dd000   KERNEL32   (deferred)             
    00007ff8`07420000 00007ff8`07775000   combase    (deferred)             
    00007ff8`07820000 00007ff8`079c0000   USER32     (deferred)             
    00007ff8`079c0000 00007ff8`079f0000   IMM32      (deferred)             
    00007ff8`07c00000 00007ff8`07c2a000   GDI32      (deferred)             
    00007ff8`08480000 00007ff8`085ab000   RPCRT4     (deferred)             
    00007ff8`085b0000 00007ff8`0864e000   msvcrt     (deferred)             
    00007ff8`08c40000 00007ff8`08cee000   shcore     (deferred)             
    00007ff8`08db0000 00007ff8`08fa5000   ntdll      (pdb symbols)          C:\ProgramData\Dbg\sym\ntdll.pdb\53F12BFE149A2F50205C8D5D66290B481\ntdll.pdb
    00007fff`f8580000 00007fff`f881a000   COMCTL32   (deferred)    
    

    若要查看堆疊追蹤,請輸入下列命令:

    k

    輸出類似於下列範例:

    0:000> k
    00 000000c8`2647f708 00007ff6`6e783d36     notepad!wWinMain
    01 000000c8`2647f710 00007ff8`07237034     notepad!__scrt_common_main_seh+0x106
    02 000000c8`2647f750 00007ff8`08e02651     KERNEL32!BaseThreadInitThunk+0x14
    03 000000c8`2647f780 00000000`00000000     ntdll!RtlUserThreadStart+0x21
    
  7. 若要再次啟動 記事本 執行,請輸入下列命令:

    g

  8. 若要中斷 記事本,請在 [檔案] 功能表上,選取 [中斷]。

  9. 若要在 設定並驗證斷點 ZwWriteFile,請輸入下列命令:

    布 ntdll!ZwWriteFile

    bl

  10. 若要再次啟動 記事本 執行,請輸入 g。 在 [記事本] 視窗中,輸入一些文字。 在 [檔案] 功能表上,選取 [儲存]。 當談到 ZwCreateFile時,執行中的程式代碼會中斷。 輸入 k 命令以查看堆疊追蹤。

    Screenshot of a stack trace in WinDbg.

    在命令行左側的 WinDbg 視窗中,會顯示處理器和線程編號。 在此範例中,目前的處理器編號為0,而目前的線程編號為11(0:011>)。 視窗會顯示處理器 0 上執行之線程 11 的堆疊追蹤。

  11. 若要檢視 記事本 程式中所有線程的清單,請輸入此命令(圖文):

    ~

    輸出類似於下列範例:

    0:011> ~
       0  Id: 5500.34d8 Suspend: 1 Teb: 000000c8`262c4000 Unfrozen
       1  Id: 5500.3960 Suspend: 1 Teb: 000000c8`262c6000 Unfrozen
        2  Id: 5500.5d68 Suspend: 1 Teb: 000000c8`262c8000 Unfrozen
        3  Id: 5500.4c90 Suspend: 1 Teb: 000000c8`262ca000 Unfrozen
        4  Id: 5500.4ac4 Suspend: 1 Teb: 000000c8`262cc000 Unfrozen
        5  Id: 5500.293c Suspend: 1 Teb: 000000c8`262ce000 Unfrozen
        6  Id: 5500.53a0 Suspend: 1 Teb: 000000c8`262d0000 Unfrozen
        7  Id: 5500.3ca4 Suspend: 1 Teb: 000000c8`262d4000 Unfrozen
        8  Id: 5500.808 Suspend: 1 Teb: 000000c8`262da000 Unfrozen
       10  Id: 5500.3940 Suspend: 1 Teb: 000000c8`262dc000 Unfrozen
     . 11  Id: 5500.28b0 Suspend: 1 Teb: 000000c8`262de000 Unfrozen
       12  Id: 5500.12bc Suspend: 1 Teb: 000000c8`262e0000 Unfrozen
       13  Id: 5500.4c34 Suspend: 1 Teb: 000000c8`262e2000 Unfrozen
    

    在此範例中,14 個線程的索引為 0 到 13。

  12. 若要檢視線程 0 的堆疊追蹤,請輸入下列命令:

    ~0s

    k

    輸出類似於下列範例:

    0:011> ~0s
    0:011> ~0s
    win32u!NtUserGetProp+0x14:
    00007ff8`06ab1204 c3              ret
    0:000> k
     # Child-SP          RetAddr               Call Site
    00 000000c8`2647bd08 00007ff8`07829fe1     win32u!NtUserGetProp+0x14
    01 000000c8`2647bd10 00007fff`f86099be     USER32!GetPropW+0xd1
    02 000000c8`2647bd40 00007ff8`07d12f4d     COMCTL32!DefSubclassProc+0x4e
    03 000000c8`2647bd90 00007fff`f8609aba     SHELL32!CAutoComplete::_EditWndProc+0xb1
    04 000000c8`2647bde0 00007fff`f86098b7     COMCTL32!CallNextSubclassProc+0x9a
    05 000000c8`2647be60 00007ff8`0782e858     COMCTL32!MasterSubclassProc+0xa7
    06 000000c8`2647bf00 00007ff8`0782de1b     USER32!UserCallWinProcCheckWow+0x2f8
    07 000000c8`2647c090 00007ff8`0782d68a     USER32!SendMessageWorker+0x70b
    08 000000c8`2647c130 00007ff8`07afa4db     USER32!SendMessageW+0xda
    
  13. 若要結束偵錯並從 記事本 進程中斷連結,請輸入下列命令:

    Qd

開啟您自己的應用程式並連結 WinDbg

例如,假設您已撰寫並建置此小型控制台應用程式:

...
void MyFunction(long p1, long p2, long p3)
{
    long x = p1 + p2 + p3;
    long y = 0;
    y = x / p2;
}

void main ()
{
    long a = 2;
    long b = 0;
    MyFunction(a, b, 5);
}

在此練習中,假設建置的應用程式 (MyApp.exe) 和符號檔 (MyApp.pdb) 位於 C:\MyApp\x64\Debug 中。 也假設應用程式原始碼位於 C:\MyApp\MyApp 中,而且目標計算機已編譯MyApp.exe。

  1. 開啟 WinDbg。

  2. 在 [ 檔案] 選單上,選取 [ 啟動可執行檔]。 在 [啟動可執行檔] 對話框中,移至 C:\MyApp\x64\Debug。 針對 [ 檔名],輸入 MyApp.exe。 選取開啟

  3. 輸入下列命令:

    .symfix

    .sympath+ C:\MyApp\x64\Debug

    這些命令會告訴 WinDbg 在何處尋找應用程式的符號和原始程式碼。 在此情況下,原始程式碼位置不需要使用 .srcpath 來設定,因為符號具有原始程序檔的完整路徑。

  4. 輸入下列命令:

    。重新載入

    bu MyApp!main

    g

    您的應用程式在函式上 main 中斷至調試程式。

    WinDbg 會顯示您的原始程式碼和 [命令] 視窗。

    Screenshot of source code displayed in WinDbg.

  5. 在 [偵錯] 功能表上,選取 [逐步執行] (或選取 F11)。 繼續逐步執行,直到您逐步執行 MyFunction為止。 當您逐步執行這一行 y = x / p2時,您的應用程式會當機並中斷至調試程式。

    輸出類似於下列範例:

    (1450.1424): Integer divide-by-zero - code c0000094 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    MyApp!MyFunction+0x44:
    00007ff6`3be11064 f77c2428    idiv  eax,dword ptr [rsp+28h] ss:00000063`2036f808=00000000
    
  6. 輸入此指令:

    !analyze -v

    WinDbg 會顯示問題的分析(在此案例中,除以 0)。

    FAULTING_IP:
    MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7]
    00007ff6`3be11064 f77c2428        idiv    eax,dword ptr [rsp+28h]
    
    EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
    ExceptionAddress: 00007ff63be11064 (MyApp!MyFunction+0x0000000000000044)
       ExceptionCode: c0000094 (Integer divide-by-zero)
      ExceptionFlags: 00000000
    NumberParameters: 0
    ...
    STACK_TEXT:  
    00000063`2036f7e0 00007ff6`3be110b8 : ... : MyApp!MyFunction+0x44
    00000063`2036f800 00007ff6`3be1141d : ... : MyApp!main+0x38
    00000063`2036f840 00007ff6`3be1154e : ... : MyApp!__tmainCRTStartup+0x19d
    00000063`2036f8b0 00007ffc`b1cf16ad : ... : MyApp!mainCRTStartup+0xe
    00000063`2036f8e0 00007ffc`b1fc4629 : ... : KERNEL32!BaseThreadInitThunk+0xd
    00000063`2036f910 00000000`00000000 : ... : ntdll!RtlUserThreadStart+0x1d
    
    STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ;dt ntdll!LdrpFailureData ;.cxr 0x0 ;kb
    
    FOLLOWUP_IP:
    MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7]
    00007ff6`3be11064 f77c2428        idiv    eax,dword ptr [rsp+28h]
    
    FAULTING_SOURCE_LINE:  c:\myapp\myapp\myapp.cpp
    
    FAULTING_SOURCE_FILE:  c:\myapp\myapp\myapp.cpp
    
    FAULTING_SOURCE_LINE_NUMBER:  7
    
    FAULTING_SOURCE_CODE:  
         3: void MyFunction(long p1, long p2, long p3)
         4: {
         5:     long x = p1 + p2 + p3;
         6:     long y = 0;
    >    7:  y = x / p2;
         8: }
         9:
        10: void main ()
        11: {
        12:     long a = 2;
    ...
    

命令摘要

另請參閱

開始使用 WinDbg (核心模式)

調試程序作業

偵錯技術

下載並安裝 WinDbg Windows 調試程式

WinDbg 功能