参考 Release版本生成调试信息 为你的Release版本程序生成 PDB 调试信息
dmp 文件生成你可以通过多种途径来得到一个dmp文件,以下给出3种. 使用Windbg 进行dump可以用Windbg Attach 某个进程,进行dump./m表示迷你dmp,/o表示覆盖文件(如果d:\testtttt.dmp已经存在). .dump /m /o d:\testtttt.dmp 使用Dr.Watson生成dump文件这是Windows的默认行为.一旦程序崩溃就会调用Dr.Watson. 使用代码手工生成dmp文件
为每个线程设置SetUnhandledExceptionFilter(MyCallBack),这样该线程中发现未处理的SEH 异常时就会进入到MyCallBack 回调中. 无聊的是虽然MyCallBack 的参数是SEH异常的结构体指针,但C++异常也会进入到MyCallBack 中.所以只要SetUnhandledExceptionFilter 就能抓到C++的异常了. 按C++标准,未处理的C++异常应当是触发unexpected.而MS 放出话说它的编译器只触发terminate.而在MFC 中居然terminate 都不触发了,直接变成了SEH 而进入了MyCallBack.
崩溃回调中使用MiniDumpWriteDump 导出异常时的上下文,所谓MiniDump就是比较小型的dump,dump 出来的文件比较小,但信息足够了我们进行分析了. 在MyCallBack 中进行MiniDumpWriteDump. MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = GetCurrentThreadId(); eInfo.ExceptionPointers = m_pExceptionInfo; eInfo.ClientPointers = FALSE; MINIDUMP_CALLBACK_INFORMATION cbMiniDump; cbMiniDump.CallbackRoutine = CExceptionReport::miniDumpCallback; cbMiniDump.CallbackParam = 0; MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, m_pExceptionInfo ? &eInfo : NULL, NULL, &cbMiniDump); Windbg 分析dmp 文件配置Windbgdmp 文件需要用Windbg 来分析.Windbg 是一种居家旅行杀人越货的必备良药. 猛击下面的链接获取Windbg:[1] 或者到 172.16.0.2 上找一下. 按 Ctrl+S 设置Symbol Path,即设置 PDB调试信息路径,有了PDB中的符号信息我们才能 将崩溃时的指令转换为函数名. 图片1 如上图 Symbol Path 有两个,被分号分隔. 一个是MS 的,MS 的推荐你设置一下,这样能看到系统DLL 的符号.不过设置了之后会下载不少的符号文件,比较慢,如果你受不了了的话就不设置啰.你也可以偶尔设置一下,偶尔让它下载一点,这样生活更轻松. 另一个必须的,是编译时生成的pdb 文件所在的路径. symsrv*symsrv.dll*e:\localsymbols*http://msdl.microsoft.com/download/symbols; E:\ccroot\zyn_KDM5.0\KDM5.0_VOB\80-OtherCu\thirdsdk\coredump\crashrpttest\src\Release 分析dmp 文件analyze -v 分析用以下代码进行测试.崩溃地址会在0x77b92f4a(不同机器会不同). CCrashRptTestDlg::OnOK 中调用TestUnHandledException,在TestUnHandledException 中有如下会导致崩溃的代码 TCHAR* p = 0; _tcsncpy(p,_T("sdf"),3); Ctrl+D 载入dmp 文件. 按ALT+1 调出Command View 在左下角输入 !analyze -v 图片1 然后按Enter 键.得到下面结果.崩溃地址0x77b92f4a,崩溃原因c0000005 (Access violation). 关键是看STACK TEXT, 从下往上看. 可以发现是OnOK 调用了TestUnHandledException, TestUnHandledException 调用了_tcsncpy, 最后在msvcrt::mbsnbcpy 的地方挂了.其中CrashRptTestDlg.cpp @ 178 行号是大致的,不精确的(应该是Release 优化的原因). ……//以上省略若干. EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff) ExceptionAddress: 77b92f4a (msvcrt!_mbsnbcpy+0x0000004f) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 00000000 Attempt to write to address 00000000 LAST_CONTROL_TRANSFER: from 0040155f to 77b92f4a STACK_TEXT(第一列是函数所压栈地址,第二列是函数地址,后面是三个参数值) 0013f7c4 00401c55 00000000 00404080 00000003 msvcrt!mbsnbcpy+0x4f 0013f7d8 00401b47 00000000 00404080 00000003 CrashRptTest!_tcsncpy+0x15 [tchar.h @ 786] 0013f848 0040161b 0000000c 0013fe8c 0013f868 CrashRptTest!TestUnHandledException+0x11c [……testhelper.cpp @ 151] 0013f858 7552e938 00000000 754e650c 0013f89c CrashRptTest!CCrashRptTestDlg::OnOK+0xe [……CrashRptTestDlg.cpp @ 178] ……//以下省略若干. 无法得到函数名时的分析以下内容来自 <<windows用户态程序高效排错>>
ChildEBP RetAddr Args to Child 0012f74c 7c821b74 77e99ea d0000144 00000004 ntdll!KiFastSystemCallRet 0012f750 77e999ea d0000144 00000004 00000000 ntdll!ZwRaiseHardError+0xc 0012f9bc 004339be 0012fa08 7ffdd000 0044c4d8 kernel32!UnHandledExceptionFilter+0x4b4 UnHandledExceptionFilter 第一个参数 0012fa08 保存的就是异常信息和异常上下文地址:
0:000> dd 0x0012fa08 0012fa08 0012faf4 0012fb10 0012fa37 7c82eeb2 0012faf4 保存了异常信息,如下文所述可用.exr查看之. 0012fb10 保存了异常上下文,如下文所述可用.cxr切换之.
0:000> .exr 0012faf4 ExceptionAddress: 0041a5a8 (release_crash!main+0x00000028) ExceptionCode: c0000005(Access violation) ExceptionFlags: 0000000 NumberParameters: 2 Pararmeter[0]: 00000001 Pararmeter[1]: 00000000 Attempt to write to address 00000000
0:000 .cxr 0012fb10 eax=00000000 ebx=7ffde000 ecx=00000000 ...... release_crash!main+0x28: 0041a5a8 c60000 mov byte ptr [eax],0x0 ds:0023:00000000=??
*** Stack trace for last set context - .thread/.cxr resets it ChildEBP RetAddr Args to Child 0012fedc 00427c90 00000001 00361748 003617d0 release_crash!main+0x28[c:\src\release_crash.cpp@51] 0012ffc0 77e523cd 00000000 00000000 7ffde000 release_crash!mainCRTStartup+0x170 0012fff0 00000000 00418b18 00000000 78746340 kernel32!BaseProcessStart+0x23(秩名) |