主要根据windows 提供的错误报告机制来捕获程序的异常。
基础知识:
MiniDump: 微软提供了一个API函数MiniDumpWriteDump(在Dbghelp.h文件中,需导入DbgHelp.lib), 它的作用就是在程序崩溃的时候,将崩溃信息写到一个dump 的后缀名的文件里,方便查找错误原因。
Windows 提供了函数 SetUnhandledExceptionFilter ,它给了我们处理异常的最后机会,否则Windows 就会正式认为这个异常没有得到处理。
我们通常应该在进程初始化阶段调用这个函数,一旦调用了这个函数,进程中任意线程抛出的未处理异常都会导致我们指定(SetUnhandledExceptionFiler的参数)的最上层过滤函数来执行。
注释:
PTOP_LEVEL_EXCEPTION_FILER SetUnhandledExceptionFilter(PTOP_LEVEL_EXCEPTION_FILERpTopLevelExceptionFiler);
LONG WINAPI TopLevelUnhandledExceptionFiler(PXCEPTION_POINTERS pExceptionInfo);
异常的过滤程序的返回值正常有3种:
EXCEPTION_EXECUTE_HANDLER 进程在不给用户通知的情况下直接终止。
ExCEPTION_CONTINUE_EXECUTION 抛出异常指令继续执行,如果异常没有处理好可能会出现死循环。
EXCEPTION_CONTINUE_SEARCH 异常不会得到任何处理。
异常捕获实例:
#include <windows.h>
#include <Dbghelp.h>
#pragma comment( lib, "DbgHelp" )
LONG WINAPI MyUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS* ExceptionInfo )
{
HANDLE lhDumpFile = CreateFile(_T("DumpFile.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL);
MINIDUMP_EXCEPTION_INFORMATION loExceptionInfo;
loExceptionInfo.ExceptionPointers = ExceptionInfo;
loExceptionInfo.ThreadId = GetCurrentThreadId();
loExceptionInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),lhDumpFile, MiniDumpNormal, &loExceptionInfo, NULL, NULL);
CloseHandle(lhDumpFile);
return EXCEPTION_EXECUTE_HANDLER;
}
void Fun2()
{
int *p = NULL;
*p = 0;
}
void Fun()
{
Fun2();
}
int main()
{
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
Fun();
return 1;
}
这是一个简单的异常捕获实例。
在实例中,我们通过捕获异常后,通过MiniDumpWriteDump 写入异常的详细报告,然后就可以通过dmp来调试异常。
Dump的调试:
基本条件,需把崩溃程序的dmp 文件,软件编译时产生的PDB文件,还有执行的EXE放在同一目录下(所有每次发布时要先保留好pdb 文件);
实例:
以上次实例生产的DMP 文件来进行调试,
方式1
首先,把dmp,pdb,exe 文件放在同一文件夹下;
然后用,WinDbg 直接打开dmp 文件,通过命令行来配置调试环境,
步骤:
1 .sympath E:/dumptest/Debug
2 .exepath E:/dumptest/Debug
3 .srcpath E:/dumptest
4 .ecxr
这样,WinDbg就能自动跳转到异常代码那行了。
方式2:
首先,把dmp,pdb,exe 文件放在同一文件夹下;
把源代码保持编译时的路径(保持开发环境),
直接用VS 打开dmp文件,然后按F5 进行调试,
注,这只是针对本机环境的调试。
Dmp高级调试,继续研究中。。。。将在下部中完善