转载自:http://www.itdaan.com/blog/2018/06/06/8f6a840999cfb69fac698a09843d0d9f.html
首先我们收集了程序崩溃的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规范) | PASCAL | stdcall | Fastcall |
参数传递顺序 | 从右到左 | 从左到右 | 从右到左 | 使用寄存器和堆栈 |
平衡堆栈者 | 调用者 | 子程序 | 子程序 | 子程序 |
允许使用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-04h | P2 | EBP+0Ch |
k-08h | P1 | EBP+08h |
k-0ch | IP | EBP+04h |
K-10h | 保存的EBP | EBP |
k-14h | 局部变量1 | EBP-4h |
k-18h | 局部变量2 | EBP-8h |
ESP | 当前ESP指针 |
函数返回值一般放在eax寄存器中返回,如果处理结果超过了eax寄存器,其高位就会放在edx寄存器中