1. 程式人生 > >windbg分析崩潰dmp

windbg分析崩潰dmp

首先我們收集了程式崩潰的dump檔案,然後將dump檔案拖拽到windbg下,然後依次如下命令:

1.設定符號路徑:.sympath srv*C:\symbols*http://msdl.microsoft.com/download/symbols;C:\crash\pdb; 備註:C:\crash\pdb 是自己程式的pdb的符號路徑。

2.鍵入:.reload,             讓windbug去重新載入符號。

3.鍵入:!analyze -v           分析就開始了

然後經過幾分鐘的等待,大概就能得到大致的分析崩潰的結果資訊:

FOLLOWUP_IP: 
msvcr120!_woutput_s_l+978 [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1629]
7438d951 663901          cmp     word ptr [ecx],ax

MOD_LIST: <ANALYSIS/>

NTGLOBALFLAG:  0

FAULTING_THREAD:  0000105c

BUGCHECK_STR:  APPLICATION_FAULT_STRING_DEREFERENCE_INVALID_POINTER_READ_FILL_PATTERN_ffffffff

PRIMARY_PROBLEM_CLASS:  STRING_DEREFERENCE_FILL_PATTERN_ffffffff

DEFAULT_BUCKET_ID:  STRING_DEREFERENCE_FILL_PATTERN_ffffffff

LAST_CONTROL_TRANSFER:  from 7438d6a6 to 7438d951

STACK_TEXT:  
001ccd30 7438d6a6 001ccd54 019121e0 00000000 msvcr120!_woutput_s_l+0x978 [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1629]
001ccd74 7438e0e7 7438d716 003fe898 000020c5 msvcr120!_vswprintf_helper+0x8e [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 157]
001ccd98 743a3600 003fe898 000020c5 019121e0 msvcr120!_vswprintf_s_l+0x43 [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 272]
001ccdb4 01219561 003fe898 000020c5 019121e0 msvcr120!swprintf_s+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]
001cce2c 0120c7da 00000002 0040a008 0000001b wuxia!KSimpleLogger::writeLog+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]
001ccf4c 7709abe6 01a69f70 029a1730 7ffde6cc wuxia!ksl_write_log+0x17a [d:\workspace\wuxiastreamer\libmisc\simple_logger.cpp @ 127]
001ccf64 5119097c 00000000 00000000 00000001 user32!CallNextHookEx+0x48
WARNING: Stack unwind information not available. Following frames may be wrong.
001cd010 76f76aee 001cd028 00000030 7f8eec35 Qt5Core+0x1b097c
001cd0f4 7709e171 00000000 00000001 770ac4b7 ntdll!KiUserCallbackDispatcher+0x2e
001cd170 770ac560 00000000 76f76aa0 00000001 user32!CallHookWithSEH+0x21
001cd204 770acc40 02fb0580 00000000 029b36e8 user32!UserCallWinProcCheckWow+0x5c
001cd214 51190613 001cd244 7f8eee35 029a1730 user32!DispatchMessageW+0xf
001cd21c 7f8eee35 029a1730 00000000 001cf038 Qt5Core+0x1b0613
001cd244 00000000 00000016 000006bf 007bbe13 0x7f8eee35


STACK_COMMAND:  ~0s; .ecxr ; kb

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  msvcr120!_woutput_s_l+978

FOLLOWUP_NAME:  MachineOwner

解釋:上面的stack_text是崩潰的上下文堆疊的回溯資訊。其實程式執行順序是從下面往上面走的,也就是大概從simple_logger.cpp的ksl_write_log函式執行logger.cpp裡面的writeLog函式,然後再呼叫swprintf_s函式,最後崩潰在output.c的_voutput_s_l這個函式(後面還可以對應相應的程式碼行號,可以清晰的指向呼叫的程式碼行)。

然後跳到相應的程式碼:

(ksl_write_log函式對應程式碼:)

int ksl_write_log(
	IN LOGGER_OBJECT loggerObject,
	IN LOG_LEVEL level,
	IN const wchar_t *format,
	IN ...
	)
{
	KSimpleLogger *logger = (KSimpleLogger*)loggerObject;
	if (!logger)
		return -1;

	_locale_t loc = global.getDefaultLocale();

	va_list arglist;
	va_start(arglist, format);

	static std::unique_ptr<wchar_t> buffer(new wchar_t[8192]);
	int cch = _vsnwprintf_s_l(buffer.get(), 8192, _TRUNCATE, __fmt.get(), loc, arglist);
	if (cch <= 0){
		return 0;
	}

	va_end(arglist);
	BOOL bRet = logger->writeLog(level, buffer.get(), cch);
	return bRet;
}
BOOL KSimpleLogger::writeLog(LOG_LEVEL level, const wchar_t *log, int cch)
{
	KSimpleLoggerGlobal &global = KSimpleLoggerGlobal::getInstance();

	wchar_t *buffer;
	int bufferLen;
	global.getBuffer(buffer, bufferLen);

	wchar_t *buf = buffer;
	int len = bufferLen - 3;	// \r\n\0

	// Head
	SYSTEMTIME st;
	GetLocalTime(&st);
	int headerLen = swprintf_s(
		buf, len, L"%04d%02d%02d_%02d:%02d:%02d %s [%s] -- ", 
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, 
		__level2String(level), 
		m_name.c_str()
		);
	if (headerLen <= 0)
	{
		return FALSE;
	}

就是崩在swprintf_s這個函式,我們知道這個crt函式是沒問題,問題肯定是我們呼叫的原因導致的崩潰了。

好,我們再看看崩潰的上下文堆疊資訊:

STACK_TEXT:  
001ccd30 7438d6a6 001ccd54 019121e0 00000000 msvcr120!_woutput_s_l+0x978 [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1629]
001ccd74 7438e0e7 7438d716 003fe898 000020c5 msvcr120!_vswprintf_helper+0x8e [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 157]
001ccd98 743a3600 003fe898 000020c5 019121e0 msvcr120!_vswprintf_s_l+0x43 [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 272]
001ccdb4 01219561 003fe898 000020c5 019121e0 msvcr120!swprintf_s+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]
001cce2c 0120c7da 00000002 0040a008 0000001b wuxia!KSimpleLogger::writeLog+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]
001ccf4c 7709abe6 01a69f70 029a1730 7ffde6cc wuxia!ksl_write_log+0x17a [d:\workspace\wuxiastreamer\libmisc\simple_logger.cpp @ 127]
001ccf64 5119097c 00000000 00000000 00000001 user32!CallNextHookEx+0x48
WARNING: Stack unwind information not available. Following frames may be wrong.
001cd010 76f76aee 001cd028 00000030 7f8eec35 Qt5Core+0x1b097c
001cd0f4 7709e171 00000000 00000001 770ac4b7 ntdll!KiUserCallbackDispatcher+0x2e
001cd170 770ac560 00000000 76f76aa0 00000001 user32!CallHookWithSEH+0x21
001cd204 770acc40 02fb0580 00000000 029b36e8 user32!UserCallWinProcCheckWow+0x5c
001cd214 51190613 001cd244 7f8eee35 029a1730 user32!DispatchMessageW+0xf
001cd21c 7f8eee35 029a1730 00000000 001cf038 Qt5Core+0x1b0613
001cd244 00000000 00000016 000006bf 007bbe13 0x7f8eee35

怎麼看呢,第一列就是ChildEbp,是函式呼叫的棧頂,第二列是函式的返回值儲存的地址資訊,然後第三個引數開始就是函式的入參了:

就拿:

001ccdb4 01219561 003fe898 000020c5 019121e0 msvcr120!swprintf_s+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]
這行來看,第三列“003fe898”開始就是入參的第一個引數,程式碼如下:
int headerLen = swprintf_s(buf, len, L"%04d%02d%02d_%02d:%02d:%02d %s [%s] -- ", 
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, 
		__level2String(level), 
		m_name.c_str()
		);

第一個引數就是buf的地址,怎麼看呢,我們鍵入:db 003fe898   就可以讀取改地址的位元組資訊。(db就是readbyte,表示一個位元組一個位元組讀取,命令dd就是readdword,表示四個位元組四個位元組讀取)

  • dw = 雙位元組WORD格式;
  • dd = 4位元組DWORD格式 ;
  • dq = 8位元組格式;
  • df = 4位元組單精度浮點數格式;
  • dD =8位元組雙精度浮點數格式;
  • dp = 指標大小格式,32位系統下4位元組,64位系統下為8位元組。

然後看看我們讀取的值:

0:000> db 003fe898 
003fe898  32 00 30 00 31 00 38 00-30 00 36 00 30 00 33 00  2.0.1.8.0.6.0.3.
003fe8a8  5f 00 30 00 37 00 3a 00-35 00 39 00 3a 00 33 00  _.0.7.:.5.9.:.3.
003fe8b8  34 00 20 00 45 00 52 00-52 00 4f 00 52 00 20 00  4. .E.R.R.O.R. .
003fe8c8  5b 00 4c 00 69 00 76 00-65 00 50 00 72 00 6f 00  [.L.i.v.e.P.r.o.
003fe8d8  74 00 6f 00 4d 00 67 00-72 00 5d 00 20 00 2d 00  t.o.M.g.r.]. .-.
003fe8e8  2d 00 20 00 50 00 43 00-53 00 5f 00 52 00 6f 00  -. .P.C.S._.R.o.
003fe8f8  6f 00 6d 00 4d 00 61 00-6e 00 61 00 67 00 65 00  o.m.M.a.n.a.g.e.
003fe908  52 00 65 00 73 00 55 00-52 00 49 00 2c 00 20 00  R.e.s.U.R.I.,. .

看起來是ok的,這裡面的buf就是相應的日誌資訊(其實是前一次列印的日誌資訊保留在buf裡面所留下的)。

然後我們看看第二個引數:000020c5,這個值十進位制就是8389,對了下程式碼,這個值也是ok的,沒發現問題,然後看第三個引數:019121e0,這個對應程式碼:L"%04d%02d%02d_%02d:%02d:%02d %s [%s] -- "引數,我們同樣db下這個地址:

0:000> db 019121e0
019121e0  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
019121f0  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912200  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912210  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912220  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912230  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912240  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912250  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????

這就奇怪了,這個地址沒有值,其實按理說,這個地址是可以讀取出值來的,對應的值就是對應的字串,現在讀取不了,肯定是該地址資訊被破壞了。當我們想看第四個引數的時候,發現後面沒有了,上面預設只顯示三個引數資訊。

然後我們想轉到該崩潰的上下文當中,用kb試試(K* 命令表示列印堆疊,kb表示列印當前執行緒堆疊並且預設顯示三個入參資訊):

0:000> kb
ChildEBP RetAddr  Args to Child              
001cc120 76f7652c 75106a8e 00000002 001cc174 ntdll!KiFastSystemCallRet
001cc124 75106a8e 00000002 001cc174 00000001 ntdll!NtWaitForMultipleObjects+0xc
001cc1c0 7574bf6e 001cc174 001cc1e8 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
001cc208 7574bfdc 00000002 7ffdf000 00000000 kernel32!WaitForMultipleObjectsExImplementation+0xe0
001cc224 657f293a 00000002 001cc250 00000000 kernel32!WaitForMultipleObjects+0x18
001cc25c 657f2a6c 00000000 7f77ca5d 657f29c0 crashreport!HandleCrashThread+0x13a [d:\workspace\wuxiastreamer\crashreport\crashreport.cpp @ 1179]
001cc288 75760a26 001cc340 7f92c8c3 00000000 crashreport!MyUnhandledExceptionFilter+0xac [d:\workspace\wuxiastreamer\crashreport\crashreport.cpp @ 1230]
001cc310 76fa786c 001cc340 76f4e52c 00000000 kernel32!UnhandledExceptionFilter+0x127
001cc318 76f4e52c 00000000 001cfaf0 76f80e78 ntdll!__RtlUserThreadStart+0x62
001cc32c 76f4e3c4 00000000 00000000 00000000 ntdll!_EH4_CallFilterFunc+0x12
001cc354 76f76cb9 fffffffe 001cfae0 001cc45c ntdll!_except_handler4+0x8e
001cc378 76f76c8b 001cc440 001cfae0 001cc45c ntdll!ExecuteHandler2+0x26
001cc39c 76f4fb9b 001cc440 001cfae0 001cc45c ntdll!ExecuteHandler+0x24
001cc428 76f76b17 001cc440 001cc45c 001cc440 ntdll!RtlDispatchException+0x127
001cc428 00000000 001cc440 001cc45c 001cc440 ntdll!KiUserExceptionDispatcher+0xf

發現不對,這不是我們想要的崩潰堆疊資訊。是不是在其他執行緒呢,可以用~*k(列印所有執行緒堆疊資訊),發現也沒有。(切換執行緒堆疊可以用:~2s(切換到二號執行緒))

想要看到崩潰堆疊需要切換到上下文當中,用:.ecxr命令,然後在kp一下(kp表示列印堆疊並附帶引數資訊):

0:002> .ecxr
eax=00000000 ebx=00000000 ecx=61476f67 edx=ffffffff esi=61476f67 edi=7ffffffe
eip=7438d951 esp=001cc89c ebp=001ccd30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
msvcr120!_woutput_s_l+0x978:
7438d951 663901          cmp     word ptr [ecx],ax        ds:0023:61476f67=????
0:002> kp
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr  
001ccd30 7438d6a6 msvcr120!_woutput_s_l(struct _iobuf * stream = 0x001ccd54, wchar_t * format = 0x01912224 "--- memory read error at address 0x01912224 ---", struct localeinfo_struct * plocinfo = 0x00000000, char * argptr = 0x001ccde8 "???")+0x978 [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1629]
001ccd74 7438e0e7 msvcr120!_vswprintf_helper(<function> * woutfn = 0x7438d716, unsigned short * string = 0x003fe898, unsigned int count = 0x20c5, wchar_t * format = 0x019121e0 "--- memory read error at address 0x019121e0 ---", struct localeinfo_struct * plocinfo = 0x00000000, char * ap = 0x001ccdc8 "???")+0x8e [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 157]
001ccd98 743a3600 msvcr120!_vswprintf_s_l(unsigned short * string = 0x003fe898, unsigned int sizeInWords = 0x20c5, wchar_t * format = 0x019121e0 "--- memory read error at address 0x019121e0 ---", struct localeinfo_struct * plocinfo = 0x00000000, char * ap = 0x001ccdc8 "???")+0x43 [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 272]
001ccdb4 01219561 msvcr120!swprintf_s(unsigned short * string = 0x003fe898, unsigned int sizeInWords = 0x20c5, wchar_t * format = 0x019121e0 "--- memory read error at address 0x019121e0 ---")+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]
001cce2c 0120c7da wuxia!KSimpleLogger::writeLog(_LOG_LEVEL level = LOG_LEVEL_ERROR (0n2), wchar_t * log = 0x0040a008 "Muted failed, errorcode:255", int cch = 0n27)+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]
001ccf4c 7709abe6 wuxia!ksl_write_log(void * loggerObject = 0x0174599c, _LOG_LEVEL level = LOG_LEVEL_ERROR (0n2), wchar_t * format = 0x01745964 "--- memory read error at address 0x01745964 ---")+0x17a [d:\workspace\wuxiastreamer\libmisc\simple_logger.cpp @ 127]
001ccf64 5119097c user32!CallNextHookEx+0x48
WARNING: Stack unwind information not available. Following frames may be wrong.
001cd010 76f76aee Qt5Core+0x1b097c
001cd0f4 7709e171 ntdll!KiUserCallbackDispatcher+0x2e
001cd170 770ac560 user32!CallHookWithSEH+0x21
001cd204 770acc40 user32!UserCallWinProcCheckWow+0x5c
001cd214 51190613 user32!DispatchMessageW+0xf
001cd21c 7f8eee35 Qt5Core+0x1b0613
001cd244 00000000 0x7f8eee35

我們還是轉到那行:

001ccdb4 01219561 msvcr120!swprintf_s(unsigned short * string = 0x003fe898, unsigned int sizeInWords = 0x20c5, wchar_t * format = 0x019121e0 "--- memory read error at address 0x019121e0 ---")+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]  

發現還是隻有三個引數啊。(因為swprintf_s是不定引數型別函式,所以只顯示了前面固定的引數資訊)

怎麼辦呢,要知道第一列(001ccdb4)是函式ebp地址資訊,我們可以用:dd 001ccdb4

0:002> dd 001ccdb4
001ccdb4  001cce2c 01219561 003fe898 000020c5
001ccdc4  019121e0 000007e2 00000006 00000003
001ccdd4  00000007 0000003b 00000022 01912124
001ccde4  61476f67 7f96c5c1 003fd390 13bcf758
001ccdf4  0174599c 0040a008 0174599c 003fe898
001cce04  01912124 000607e2 00030000 003b0007
001cce14  01040022 7f96c5c1 00000000 001ccf18
001cce24  016e5f8e ffffffff 001cce5c 0120c7da

好了,引數資訊都在裡面了:第一個引數:0x003fe898  第二個引數000020c5(8389) 第三個引數是019121e0,第四個引數是000007e2(十進位制是2018) 第五個引數00000006  第六個引數是00000003  第七個引數是00000007   第八個引數是0000003b   第九個引數是00000022       第十個引數是01912124    第十一個引數是61476f67

swprintf_s(buf, len, L"%04d%02d%02d_%02d:%02d:%02d %s [%s] -- ", 
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, 
		__level2String(level),                      //第十個引數
		m_name.c_str()                             //第11個引數
		);

我們看看第十個引數和第十一個引數資訊:

0:002> db 01912124
01912124  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912134  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912144  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912154  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912164  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912174  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912184  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
01912194  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
0:002> db 61476f67
61476f67  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476f77  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476f87  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476f97  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476fa7  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476fb7  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476fc7  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
61476fd7  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????

什麼都沒有。 好,感覺這條路走不下去了。

我們再看看上面的函式的呼叫情況吧:

001cce2c 0120c7da wuxia!KSimpleLogger::writeLog(_LOG_LEVEL level = LOG_LEVEL_ERROR (0n2), wchar_t * log = 0x0040a008 "Muted failed, errorcode:255", int cch = 0n27)+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]

我們可以轉到這行堆疊,然後看看裡面的細節:

先用kn  (表示第一列顯示顯示堆疊列號)

0:002> kn
  *** Stack trace for last set context - .thread/.cxr resets it
 # ChildEBP RetAddr  
00 001ccd30 7438d6a6 msvcr120!_woutput_s_l+0x978 [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1629]
01 001ccd74 7438e0e7 msvcr120!_vswprintf_helper+0x8e [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 157]
02 001ccd98 743a3600 msvcr120!_vswprintf_s_l+0x43 [f:\dd\vctools\crt\crtw32\stdio\vswprint.c @ 272]
03 001ccdb4 01219561 msvcr120!swprintf_s+0x17 [f:\dd\vctools\crt\crtw32\stdio\swprintf.c @ 243]
04 001cce2c 0120c7da wuxia!KSimpleLogger::writeLog+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]
05 001ccf4c 7709abe6 wuxia!ksl_write_log+0x17a [d:\workspace\wuxiastreamer\libmisc\simple_logger.cpp @ 127]
06 001ccf64 5119097c user32!CallNextHookEx+0x48
WARNING: Stack unwind information not available. Following frames may be wrong.
07 001cd010 76f76aee Qt5Core+0x1b097c
08 001cd0f4 7709e171 ntdll!KiUserCallbackDispatcher+0x2e
09 001cd170 770ac560 user32!CallHookWithSEH+0x21
0a 001cd204 770acc40 user32!UserCallWinProcCheckWow+0x5c

好,轉到wuxia!KSimpleLogger::writeLog這行堆疊用:.frame 4 (如果想轉到下一行用 :.frame 5)

0:002> .frame 4
04 001cce2c 0120c7da wuxia!KSimpleLogger::writeLog+0xd1 [d:\workspace\wuxiastreamer\libmisc\logger.cpp @ 321]

然後可以用:dv來列印臨時變數資訊:

0:002> dv
Unable to find processor type for C:\Program Files\wuxia\1.0.0.13\wuxia.exe, using default
           this = 0x61476f67
          level = LOG_LEVEL_ERROR (0n2)
            log = 0x0040a008 "Muted failed, errorcode:255"
            cch = 0n27
             st = struct _SYSTEMTIME
      dwWritten = 0x174599c

這裡可以看到log資訊是:"Muted failed, errorcode:255"

然後找到這個對應的程式碼:

{
	if (RES_SUCCESS == res)
	{
		content = tr("Muted successfully");
	}
	else
	{
		content = QString(tr("Muted failed, please check your net!"));
		KSL_LOG_ERROR(LOG_TAG, "Muted failed, errorcode:%d", res);
	}
}
break;

然後看看:

#define KSL_LOG_ERROR(logger, format, ...) \
	ksl_write_log(logger, LOG_LEVEL_ERROR, _KSL_WSTR(format), __VA_ARGS__)

#define KSL_LOG_ERROREX(name, format, ...) \
	ksl_write_log(KSL_GET_LOGGER(name), LOG_LEVEL_ERROR, _KSL_WSTR(format), __VA_ARGS__)

發現原來這個函式用錯了,其實應該用下面的:KSL_LOG_ERROREX,如果錯誤的使用上面的函式必然導致不確定的崩潰。

附錄:

1.堆疊方式:

約定型別__cdecl(C規範)PASCALstdcallFastcall
引數傳遞順序從右到左從左到右從右到左使用暫存器和堆疊
平衡堆疊者呼叫者子程式子程式子程式
允許使用VARARG(不定引數)
函式內部呼叫,如test(p1,p2)
push p2
push p1
call test
{
push ebp //保護原有的EBP
mov ebp,esp//EBP指向棧頂
mov eax,dword ptr [ebp+0c]//呼叫引數2
mov ebx,dword ptr [ebp+08]//呼叫引數1
sub esp,8若函式要用區域性變數,則要在堆疊中留出點空間

....

add esp,8//釋放區域性變數所佔的堆疊

pop ebp//恢復現場ebp指標

ret 8,返回ret後的值為引數個數x4h
}

不理解就畫個圖:

K起始堆疊
k-04hP2EBP+0Ch
k-08hP1EBP+08h
k-0chIPEBP+04h
K-10h儲存的EBPEBP
k-14h區域性變數1EBP-4h
k-18h區域性變數2EBP-8h
ESP當前ESP指標

函式返回值一般放在eax暫存器中返回,如果處理結果超過了eax暫存器,其高位就會放在edx暫存器中