使用场景:

Win32程序在release模式下编译完成,发送给最终用户使用时,我们的程序有时候也会出现崩溃的情况,这个时候如果能快速定位崩溃原因或提供一些程序崩溃时的状态信息,对我们解决问题将会带来很大的帮助。一般程序崩溃时我们需要搜集的信息包括:系统信息、CPU寄存器信息、堆栈信息、调用堆栈信息、CPU和内存状态、内存当前地址等。调用堆栈是我们最常用到的。

技术方案:

目前我搜集的方法有以下三种,日志记录、dbghelp(.dmp) 、SHE(Structured Exception Handling)。

上一篇提供日志记录的实现方法,此篇提供一个基于dbghelp生成dump文件,同时使用符号文件和Windbg跟踪和分析系统出现的bug。

注意:SetUnhandledExceptionFilter,函数可以捕获大部分的异常,但栈溢出、覆盖产生的异常可能捕获不到。

案例演示:

如果系统在Windows kit下没有对应的库,在MSDN上下载 Windows 驱动程序工具包 (WDK) 和 Windows 调试工具 (WinDbg) 。

下载地址:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms679294(v=vs.85).aspx

  Install Debugging Tools for Windows 32-bit Version
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
  Install Debugging Tools for Windows 64-bit Versions
http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx

安装后,查看此目录

示例代码:

SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)主要通过这个异常过滤的函数来实现。

 1 // dbghelpSample.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <Windows.h>
 6 #include <iostream>
 7 #include "dbghelp.h"
 8 
 9 #pragma comment(lib, "dbghelp.lib")
10 
11  
12 LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionInfo)
13 {
14      
15     HANDLE hFile = CreateFile(_T("project.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
16     MINIDUMP_EXCEPTION_INFORMATION stExceptionParam;
17     stExceptionParam.ThreadId = GetCurrentThreadId();
18     stExceptionParam.ExceptionPointers = pExceptionInfo;
19     stExceptionParam.ClientPointers = FALSE;
20     MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithFullMemory, &stExceptionParam, NULL, NULL);
21     CloseHandle(hFile);
22  
23     return EXCEPTION_EXECUTE_HANDLER;
24     //EXCEPTION_EXECUTE_HANDLER equ 1 表示我已经处理了异常, 可以优雅地结束了
25     //EXCEPTION_CONTINUE_SEARCH equ 0 表示我不处理, 其他人来吧, 于是windows调用默认的处理程序显示一个错误框, 并结束
26     //EXCEPTION_CONTINUE_EXECUTION equ - 1 表示错误已经被修复, 请从异常发生处继续执行
27 }
28 
29 int _tmain(int argc, _TCHAR* argv[])
30 {
31     //进入主函数。
32     SetUnhandledExceptionFilter(TopLevelExceptionFilter);
33     int *pVar = NULL;
34     *pVar = 1;  //创建一个异常。程序编译不会出问题,但在执行时会因为没有分配内存而程序崩溃。
35     printf("测试");
36     return 0;
37 }
View Code

在Release模式下,编译项目,运动生成后的exe,就会当前目录下生成project.dmp 文件。

 

通过.dmp文件进行release版本程序的调试,除了使用WinDbg,也可以用 VisualStudio进调试。

 

(一) 使用WinDbg进行调试

 

(1)设置符号文件。

 

 

(2)打开.dmp文件

 

 

 

 

 

 

在WinDbg命令中输入“!analyze -v”命令。进一步详细分析异常出现的信息。

 

 

 

(二)使用VS进行.dmp进行调试。

 提示:将.dmp放到程序编译的exe旁边。

 

 

 

 

参考:

http://support.icafe8.com/technologynews/focus/932.html

http://blog.csdn.net/longlong530/article/details/43307249

http://www.cnblogs.com/happyhippy/archive/2007/04/08/710933.html

http://www.cnblogs.com/appsucc/p/3458906.html

 

posted on 2017-07-20 17:40  蒙遥  阅读(885)  评论(0编辑  收藏  举报