searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

windbg分析崩溃dmp

2023-05-07 13:41:37
100
0

首先我们收集了程序崩溃的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这个函数(后面还可以对应相应的代码行号,可以清晰的指向调用的代码行)。

然后跳到相应的代码:

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,如果错误的使用上面的函数必然导致不确定的崩溃。

0条评论
0 / 1000
廖****龙
11文章数
2粉丝数
廖****龙
11 文章 | 2 粉丝
原创

windbg分析崩溃dmp

2023-05-07 13:41:37
100
0

首先我们收集了程序崩溃的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这个函数(后面还可以对应相应的代码行号,可以清晰的指向调用的代码行)。

然后跳到相应的代码:

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,如果错误的使用上面的函数必然导致不确定的崩溃。

文章来自个人专栏
个人原创文章
11 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0