WinDbg Tutorial

Windows Debuggers: Part 1: A WinDbg Tutorial

Original Article:
Windows Debuggers: Part 1: A  WinDbg Tutorial  http://www.codeproject.com/KB/debug/windbg_part1.aspx

Introduction
在我的職業生涯中,我看見大部分的人都使用 Visual Studio 來做 debug 的工作,但是實際上還有許多其他免費的 debugger 可以使用。你會想要有這樣 debugger 是有許多理由的,例如有時候在電腦沒有開發環境的時候,但是莫名其妙crash的問題卻是層出不窮。如果可以直接從 stack dump 中觀察,可以直接找出可能是某個軟體出了問題。

目前沒有一個快速的教學可以幫助你了解  windbg,因此這裡採用 example 教學的方式,讓你多了解  windbg 帶來 degger 工作中的便利與使用方式。

WinDbg
WinDbg 是一個把 NTSD 和 KD 包裝起來的一個UI軟體,他提供 command line 的方式來輸入指令,指令大致上分成三種類型:
  • regular commands (e.g.: k). The regular commands are to debug processes.
  • dot commands (e.g.: .sympath). The dot commands are to control the debugger.
  • extension commands (e.g.: !handle) – these are custom commands that you can add to WinDbg; they are implemented as exported functions in extension DLLs
PDB Files
PDB files 是由 Linker 產生的 program database,Private PDB files 包含了 private symbols、public symbols、source lines、types、locals、globals 的資訊。而 Puliblic PDB files 不包含types、locals、globals 的資訊。
##ReadMore##
Debugging Scenario

Debugging Exception
debugger 有兩次處理 exeption 的機會。當 exception 發生時,debugger 會在 application 處理此exception 之前獲得通知 ("first-chance exception")。假如 application 沒有去主動處理這個exception,debugger 仍然有第二次機會來處理這個 exception ("second-chance exception")。最後假如 debugger 也沒有嘗試解決此exception,那麼 application 就會被終止。

.lastevent
!analyze  –v

以上兩行指令都可以顯示 exception 發生時的 exception record 和 stack trace of the function。你也可以使用  .exr,  .cxr 和  .ecxr 指令來顯示 exception 和 context records。

WinDbg Feature

Debugger Extension DLLs

DumpFiles
可以透過 dump 的功能把 process 在某個時間點上的狀態 sanpshop 下來。一個 mini-dump 的檔案大小是滿小的,除非你使用 full-memory minidump ( .dump /mf)。通常我們也會將 handle 的資訊 dump 下來 ( .dump/mfh)。mini-dump 包含所有 thread 的資訊,例如 stacks 和 list of loaded modulesm,而 full dump 則包含了較多的資訊,像是 the process heap。

Crash Dump Analysis
如果 crash 發生在 Window OS上的時候,我們可以將當時的狀況給 dump 下來。首先打開 Task Manager ,在 Processes Tab 中找到發生 crash 的那個 process,滑鼠作 right - click 會跳出 pop up menu,接著選擇 Create Dump File,稍等一點時間,會在跳出一個 message box 告訴你 dump file 在哪裡,這個 dump file 裡頭就有當時 crash 的相關資訊, windbg 就可以利用這份資料來做分析。

想要分析 dump file,請依造下來步驟來執行:

Step 1: In  WinDbg, File->’Open Crash Dump’, and point to the dump file
Step 2:  WinDbg will show you the instruction your app was executing when it crashed.
Step 3: Set your symbol path and source path properly.

假如你的 symbol 沒辦法 match,你可能會有一個很艱難的時候去了解程式的流程。如果 symbol 可以和source file 相符合的話,你可能就可以很快找到問題的所在點。

WinDbg Settings

Symbol Files and Directories
通常我們在除錯的過程中都需要symbol來幫助我們更有效的除錯。Symbol files 可以是 COFF 或是 PDB 的格式。Private symbol files 包含 functions、local and global variables 和 line information,line information用來幫助 assmbly code 對應到 source code。通常我們將 public symbol files 提供給客戶,裡頭只包含 public members 相關的資訊。

你可以透過  windbg 上的 UI 來設定 symbol path (File->Symbol File Path),或者透過  windbg 中的 command 方式來下指令。

指令的原型如下:
.sympath+ SRV*downstream_store*http://msdl.microsoft.com/download/symbols

實際的指令可能像這個樣子:
.sympath+ SRV*C:/symbols*http://msdl.microsoft.com/download/symbols
當我們從symbol server上下載 symbol 後會存放到 C:/symbols 裡頭。而 Microsoft 提供的只有 public symbol files。假如你只有 public symbol file,你只可以從 call stack 中看見 function names and their arguments。假如 binary (DLL or exe) 和 PDB 都是從你自己的 applicaiton 中產生的話,你可以額外看見 private functions, local variables and type information。

有時候可能在使用  windbg 的時候,發現顯示出來的 call stack 或是其他資訊有點怪怪時,可以重新 reload symbol,因為有時候  windbg 會偷懶,直接找近似的 symbol 來做 match.

.reload

Source Code Directories
你可以透過  windbg 上的 UI 來設定 symbol path (File->Source File Path) 或是用  .srcpath 從  win dbg 的 command 來下指令。

Breakingpoints, Tracing
  • Set soft breakpoints using the bp commands or using the toolbar breakpoint icon.
  • Set hard breakpoints using code like DbgBreakPoint() or KdBreakPoint().
  • Use tracing routines DbgPrintKdPrintOutputDebugString to print out to the WinDbg output window, from debugger extension DLLs.
Example


Example 1
這個例子是說明有一個 thread 拿了 critical section 後並沒有釋放掉,造成另一條 thread 想要拿這個 critical section 的使用拿不到,並且無限的等待。

#include <Windows.h>

CRITICAL_SECTION cs;

DWORD WINAPI newThreadProc(LPVOID lpParameter)
{
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
return 0;
}
void Example1()
{
DWORD tid = 0;
HANDLE hThread = CreateThread(NULL, 0, newThreadProc, NULL, 0, &tid); // let the thread execute immediately

WaitForSingleObject(hThread, INFINITE);
EnterCriticalSection(&cs);
}
void main()
{
Example1();
}

首先在  windbg 中打入 ~*kb,會有下面的資料出在畫面上:
  • ~: Lists all threads
  • *: Specify process id
  • kb: Displays stack trace of current thread. Kb causes the display to include the first three parameters passed to each function.
0:001> ~*kb

0 Id: 1208.115c Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr Args to Child
002bf978 776e5620 776be16a 00000024 00000000 ntdll!KiFastSystemCallRet
002bf97c 776be16a 00000024 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
002bf9e0 776be04d 00000000 00000000 7ffd8000 ntdll!RtlpWaitOnCriticalSection+0x155
*** WARNING: Unable to verify checksum for C:/Users/derek.chen/Desktop/WinDebugTest/Debug/WinDebugTest.exe
002bfa08 00c014ba 00c07140 002bfbcc 00000000 ntdll!RtlEnterCriticalSection+0x152
002bfaf8 00c01553 00000000 00000000 7ffd8000 WinDebugTest!Example1+0x6a [c:/users/derek.chen/desktop/windebugtest/example1.cpp @ 18]
002bfbcc 00c01af8 00000001 007b1a88 007b1db0 WinDebugTest!main+0x23 [c:/users/derek.chen/desktop/windebugtest/example1.cpp @ 24]
002bfc1c 00c0193f 002bfc30 7716d0e9 7ffd8000 WinDebugTest!__tmainCRTStartup+0x1a8 [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 586]
002bfc24 7716d0e9 7ffd8000 002bfc70 776c19bb WinDebugTest!mainCRTStartup+0xf [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 403]
002bfc30 776c19bb 7ffd8000 76dad664 00000000 kernel32!BaseThreadInitThunk+0xe
002bfc70 776c198e 00c0111d 7ffd8000 00000000 ntdll!__RtlUserThreadStart+0x23
002bfc88 00000000 00c0111d 7ffd8000 00000000 ntdll!_RtlUserThreadStart+0x1b

# 1 Id: 1208.1318 Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr Args to Child
009df974 7770c9a0 766cd3b0 00000000 00000000 ntdll!DbgBreakPoint
009df9a4 7716d0e9 00000000 009df9f0 776c19bb ntdll!DbgUiRemoteBreakin+0x3c
009df9b0 776c19bb 00000000 766cd3e4 00000000 kernel32!BaseThreadInitThunk+0xe
009df9f0 776c198e 7770c964 00000000 00000000 ntdll!__RtlUserThreadStart+0x23
009dfa08 00000000 7770c964 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b

我們可以發現 thread 0 停在 RtlEnterCriticalSection,合理的判斷是他拿不到 critical section,因此常試去解讀第一個 argument,裡頭帶有 critical section 的相關訊息。在 command 中打入  dt。
  • Dt [dt module!typedef adr]: Dump type. Will dump the contents of the memory using typedef as a template.
0:001> dt 00c07140
cs
+0x000 DebugInfo : 0x77746640 _RTL_CRITICAL_SECTION_DEBUG
+0x004 LockCount : -6
+0x008 RecursionCount : 1
+0x00c OwningThread : 0x0000117c
+0x010 LockSemaphore : 0x00000024
+0x014 SpinCount : 0

我們發現此 critical section 被 0x0000117c thread 拿住了。然後再去查看目前所有的 thread id.

0:001> ~
. 0 Id: 1208.115c Suspend: 1 Teb: 7ffdf000 Unfrozen
. 1 Id: 1208.1318 Suspend: 1 Teb: 7ffde000 Unfrozen

最後發現目前的所有 thread 並不包括 0x0000117c,所以最後可以知道是一個生命週期已經結束的 thread 沒有正確釋放掉 critical section。


Example 2

第二個例子滿簡單的,就是常見 Divide by zero 的 exception
void Example2()
{
int y = 71;
y = y / (71 - y);
}

void main()
{
Example2();
}


根據我自己嘗試的結果,如果直接執行執行檔,然後在用  windbg 去 attatch to a process,無法直接看到此 exception 訊息,效果比較不好。如果透過  windbg 直接將此執行檔執行起來,可以很容易發現 divide by zero 的問題。

首先我們先透過  windbg 的 UI,File -> Open Executable,選擇 Example2 的執行檔。接著打入  g . 表示我們要開始跑這個程式,畫面如下:
  • g: The g command starts executing the given process or thread. Execution will halt at the end of the program, when BreakAddress is hit, or when another event causes the debugger to stop.
0:000> g
(1090.11a0): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000047 ebx=7ffd5000 ecx=00000000 edx=00000000 esi=00000000 edi=0014fb68
eip=010f13d1 esp=0014fa90 ebp=0014fb68 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
*** WARNING: Unable to verify checksum for WinDebugTest.exe
WinDebugTest!Example2+0x31:
010f13d1 f7f9 idiv eax,ecx

我們可以發現訊息中就顯示了 Integer divide-by-zero 的問題,接著我們打入  u  eip,來看看目前程式執行的 assembly code。
  • u (Unassemble): The u command displays an assembly translation of the specified program code in memory.
  • eip: The eip register points to the memory address which the processor will next attempt to execute
0:000> u eip
WinDebugTest!Example2+0x31 [c:/users/derek.chen/desktop/windebugtest/example2.cpp @ 4]:
010f13d1 f7f9 idiv eax,ecx
010f13d3 8945f8 mov dword ptr [ebp-8],eax
010f13d6 5f pop edi
010f13d7 5e pop esi
010f13d8 5b pop ebx
010f13d9 8be5 mov esp,ebp
010f13db 5d pop ebp
010f13dc c3 ret

大家如果對組語有一點熟悉的話,應該可以發現 idiv 就是整數除法的意思,接著來看看分母是多少,所以就要看 ecx 這個值,打入  r ecx。
  • r: The r command displays or modifies registers, floating-point registers, flags, pseudo-registers, and fixed-name aliases.
0:000> r ecx
ecx=00000000

最後發現分母為0,在整數除法中是不允許的。


Example 3

這個例子是幫助大家熟悉  windbg 中使用 break point 的操作。基本上就是將 break point 設定在 k = rand(); 這行程式碼上,然後列印出 k 的值。

#include <stdlib.h>

void Example3()
{
int k = 0;
for (int i = 0; i < 5; ++i)
{
k = rand();
}
}

void main()
{
Example3();
}


首先,我們還是透過 File -> Open Executable 的方式來跑執行檔,然後打入  bp WinDebugTest!Example3,這樣我們就成功將 break point 設定在 Example3() 函式,接著打入  g, 讓執行檔開始跑。
  • bp: sets a new breakpoint at the address of the breakpoint location that is specified in the command.
  • WinDebugTest!Example3: 這個欄位放的是module name,如果沒有是唯一性,debugger不會在symbol上產生混淆,是可以不用給定。Example3這個是 function name。"!" 這個符號是連接 module name 和 function name。
0:000>0:000> bp WinDebugTest!Example3
*** WARNING: Unable to verify checksum for WinDebugTest.exe
0:000> g
Breakpoint 0 hit
eax=cccccccc ebx=7ffda000 ecx=00000000 edx=00000001 esi=00000000 edi=0024f774
eip=008213b0 esp=0024f6a4 ebp=0024f774 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
WinDebugTest!Example3:
008213b0 55 push ebp


接著很快就發現程式又停了下來,這就是我們剛剛的 break point 的功勞。如果有設定 source path 或者有時候  windbg 很聰明,會自動將執行檔位置的 source 自動讀取進來,現在應該可以發現 source 已經顯示在  windbg 上了。接著按  F10 三次,試著將程式執行的位置移動到 k = rand()。這時候我們打入  ~*kb 來觀察一下目前的 code stack,可以發現 k = rand() 這行程式的記憶體位置應該是 Example3+0x3d 。

0:000> ~*kb

. 0 Id: 12f4.11e4 Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr Args to Child
0024f6a0 00821453 00000000 00000000 7ffda000 WinDebugTest!Example3+0x3d [c:/users/derek.chen/desktop/windebugtest/example3.cpp @ 8]
0024f774 008219e8 00000001 00103308 00101e30 WinDebugTest!main+0x23 [c:/users/derek.chen/desktop/windebugtest/example3.cpp @ 15]
0024f7c4 0082182f 0024f7d8 7758d0e9 7ffda000 WinDebugTest!__tmainCRTStartup+0x1a8 [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 586]
0024f7cc 7758d0e9 7ffda000 0024f818 77bb19bb WinDebugTest!mainCRTStartup+0xf [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 403]
WARNING: Stack unwind information not available. Following frames may be wrong.
0024f7d8 77bb19bb 7ffda000 77237d52 00000000 kernel32!BaseThreadInitThunk+0x12
0024f818 77bb198e 00821113 7ffda000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0024f830 00000000 00821113 7ffda000 00000000 ntdll!RtlInitializeExceptionChain+0x36


接著我們要先將原來的 break point 刪除,打入  bl 將所有的 break point 顯示出來。接著打 bc0 將編號 0的 break point 刪除,為了確定真得已經刪除掉了,再次打入 bl 來做驗證,發現全部都不見了。
  • bl: The bl command lists information about existing breakpoints
  • bc: The bc command permanently removes previously set breakpoints from the system.
0:000> bl
0 e 008213b0 [c:/users/derek.chen/desktop/windebugtest/example3.cpp @ 4] 0001 (0001) 0:**** WinDebugTest!Example3
0:000> bc0
0:000> bl


然後我們要設定新的 break point,打入  bp WinDebugTest!Example3+0x3d "dd k L1; .echo hello world; g"。也就是希望將 k 值印出來,順便在印一句 hello world,然後再繼續跑。可以發現畫面上的訊息正如我們所期待的樣子,以第一行為例,0024f698是 k變數記憶體中的位置,00000029是他的value。
  • d*: The d* commands display the contents of memory in the given range.
  • dd: Double-word values (4 bytes)
  • L1: 從k variable開始列印1個DWORD
  • .echo: The .echo command displays a comment string.
  • ; : 用來表示此指令結束,然後可以承接下一個指令。
0:000> g
0024f698 00000029
hello world
0024f698 00004823
hello world
0024f698 000018be
hello world
0024f698 00006784
hello world
eax=57174340 ebx=7ffda000 ecx=571212c4 edx=571212c4 esi=00000000 edi=00000000
eip=77bd5e74 esp=0024f6e8 ebp=0024f6f8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
77bd5e74 c3 ret


Example 4

這個例子示範當我們將一個 constant value 指定給一個尚未初始化的指標時所產生的問題。

#include <stdio.h>

void Example4()
{
int* i = NULL;
*i = 80;
}

void main()
{
Example4();
}

首先就直接讓執行檔跑起來吧,打入 g。

0:000> g
(a40.e0c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=7ffd3000 ecx=00000000 edx=00000001 esi=00000000 edi=0021fce4
eip=00a913c8 esp=0021fc0c ebp=0021fce4 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010216
*** WARNING: Unable to verify checksum for WinDebugTest.exe
WinDebugTest!Example4+0x28:
00a913c8 c70050000000 mov dword ptr [eax],50h ds:0023:00000000=????????

從  windbg 中就已經發現有 access violation的問題了。那我們來看看目前的組語吧。打入  u。

0:000> u
WinDebugTest!Example4+0x28 [c:/users/derek.chen/desktop/windebugtest/example4.cpp @ 6]:
00a913c8 c70050000000 mov dword ptr [eax],50h
00a913ce 5f pop edi
00a913cf 5e pop esi
00a913d0 5b pop ebx
00a913d1 8be5 mov esp,ebp
00a913d3 5d pop ebp
00a913d4 c3 ret
00a913d5 cc int 3

看到第一行是一個 mov 的動作,大概就是常見的 eax裡面所含的記憶體位置是不合法的。打入  r eax,看一下他的內容。

0:000> r eax
eax=00000000


Example 5

第五個例子是展示我們不小心將同一個記憶體位置區段做了兩次的 delete動作。

#include <string.h>

void Example5()
{
char* str = new char[20];
delete [] str;
delete [] str; // error!
strcpy(str, "hi");
}

void main()
{
Example5();
}

首先先將執行檔跑起來,會跳出一個exception視窗警告你,這時候不要將視窗關掉,先用  windbg 做 attach 動作。然後直接打入  ~* 看一下目前所有的 process 資訊。

0:001> ~*
0 Id: 8a4.8e8 Suspend: 1 Teb: 7ffdf000 Unfrozen
Start: WinDebugTest!ILT+280(_mainCRTStartup) (00d7111d)
Priority: 0 Priority class: 32 Affinity: 3
. 1 Id: 8a4.15a0 Suspend: 1 Teb: 7ffde000 Unfrozen
Start: ntdll!DbgUiRemoteBreakin (77bfc964)
Priority: 0 Priority class: 32 Affinity: 3

應該可以發現 process 1 旁邊有個小句點,代表目前使用的是 process 1,但是我們的程式 WinDebugTest 卻是在 process 2。所以打入  ~0s 來做切換 thread 的動作。然後再重複打一次  ~* 看一下目前的情況
  • ~s (change current processor): The ~s command sets which processor is debugged on a multiprocessor system.
0:001>0:001> ~0s
eax=00290f00 ebx=00000000 ecx=00000000 edx=00000000 esi=00e27090 edi=00000000
eip=77bd5e74 esp=00165250 ebp=00165284 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
77bd5e74 c3 ret
0:000> ~*
. 0 Id: 8a4.8e8 Suspend: 1 Teb: 7ffdf000 Unfrozen
Start: WinDebugTest!ILT+280(_mainCRTStartup) (00d7111d)
Priority: 0 Priority class: 32 Affinity: 3
# 1 Id: 8a4.15a0 Suspend: 1 Teb: 7ffde000 Unfrozen
Start: ntdll!DbgUiRemoteBreakin (77bfc964)
Priority: 0 Priority class: 32 Affinity: 3

這個時候只要打  kb 觀察我們所在 thread 的 code stack 狀況。

0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
00165284 777c2dc0 00450b8c 00000000 00000001 ntdll!KiFastSystemCallRet
001652ac 777ecd48 77790000 00264170 00000000 USER32!SoundSentry+0x20f
0016534c 777ed2ca 00012012 0016fa28 00000000 USER32!SoftModalMessageBox+0x69d
0016549c 777ed3fc 001654a8 00000028 00000000 USER32!SoftModalMessageBox+0xc1f
001654f4 777ed678 00000000 001657e0 5e2a3438 USER32!MessageBoxTimeoutW+0x7f
00165514 777ed714 00000000 001657e0 5e2a3438 USER32!MessageBoxExW+0x1b
00165530 5e3734e6 00000000 001657e0 5e2a3438 USER32!MessageBoxW+0x45
00165584 5e35e75c 001657e0 5e2a3438 00012012 MSVCR90D!strerror_s+0x346
001677f0 5e366640 00000002 5e2a5b90 0016a860 MSVCR90D!CrtSetReportHookW2+0x71c
0016f890 5e35e392 00000002 5e2a5b90 00000034 MSVCR90D!VCrtDbgReportW+0x8e0
0016f8b0 5e35e7db 00000002 5e2a5b90 00000034 MSVCR90D!CrtSetReportHookW2+0x352
0016f8d8 5e363230 00000002 5e2a5b90 00000034 MSVCR90D!_CrtDbgReportW+0x2b
0016f920 00d71424 00812f60 0016fafc 00000000 MSVCR90D!operator delete+0xa0
0016fa28 00d71493 00000000 00000000 7ffd6000 WinDebugTest!Example5+0x64 [c:/users/derek.chen/desktop/windebugtest/example5.cpp @ 7]
0016fafc 00d71a38 00000001 00811a88 00811d60 WinDebugTest!main+0x23 [c:/users/derek.chen/desktop/windebugtest/example5.cpp @ 14]
0016fb4c 00d7187f 0016fb60 7758d0e9 7ffd6000 WinDebugTest!__tmainCRTStartup+0x1a8 [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 586]
0016fb54 7758d0e9 7ffd6000 0016fba0 77bb19bb WinDebugTest!mainCRTStartup+0xf [f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c @ 403]
0016fb60 77bb19bb 7ffd6000 76f35df6 00000000 kernel32!BaseThreadInitThunk+0x12
0016fba0 77bb198e 00d7111d 7ffd6000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0016fbb8 00000000 00d7111d 7ffd6000 00000000 ntdll!RtlInitializeExceptionChain+0x36

可以發現目前正處於彈出一個 message box 的狀態,然後仔細在看一下,有一行 MSVCR90D!operator delete+0xa0 ,看起來好像就是這行出了問題。


Example 6

第六個例子是關於 stack over flow 的問題。

void Example6_2();

void Example6_1()
{
Example6_2();
}

void Example6_2()
{
Example6_1();
}

void main()
{
Example6_1();
}

首先就直接讓執行檔跑起來吧,打入g。

0:000> g
(10c4.934): Stack overflow - code c00000fd (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=cccccccc ebx=7ffdf000 ecx=00000000 edx=00000001 esi=00000000 edi=0013316c
eip=00f113b9 esp=00132fd8 ebp=00133098 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
*** WARNING: Unable to verify checksum for WinDebugTest.exe
WinDebugTest!Example6_1+0x9:
00f113b9 53 push ebx

windbg 上面就顯示了"Stack overflow"。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值