未处理异常的捕获发送及简单调试(上部)

    技术2025-03-06  51

    主要根据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高级调试,继续研究中。。。。将在下部中完善

    最新回复(0)