• Windows捕捉系统异常


     

    参考:http://blog.csdn.net/starlee/article/details/6618849

     

    #include <Windows.h>

    #include <tchar.h>

    #include <stdio.h>

    #include <iostream>

    #include <vector>

    #include <iomanip>

    #include <DbgHelp.h>

     

    // 添加对dbghelp.lib的编译依赖

    //

    #pragma comment(lib, "dbghelp.lib")

     

    using namespace std;

     

    const int MAX_ADDRESS_LENGTH = 32;

    const int MAX_NAME_LENGTH = 1024;

     

     

    // CallStack信息

    //

    struct CallStackInfo

    {

    CHAR ModuleName[MAX_NAME_LENGTH];

    CHAR MethodName[MAX_NAME_LENGTH];

    CHAR FileName[MAX_NAME_LENGTH];

    CHAR LineNumber[MAX_NAME_LENGTH];

    };

     

     

    // 得到CallStack信息

    //

    vector<CallStackInfo> GetCallStack(const CONTEXT *pContext)

    {

    HANDLE hProcess = GetCurrentProcess();

     

    SymInitialize(hProcess, NULL, TRUE);

     

    CONTEXT c = *pContext;

     

    STACKFRAME64 sf;

    memset(&sf, 0, sizeof(STACKFRAME64));

    DWORD dwImageType = IMAGE_FILE_MACHINE_I386;

     

    // 不同的CPU类型,具体信息可查询MSDN

    //

    #ifdef _M_IX86

    sf.AddrPC.Offset = c.Eip;

    sf.AddrPC.Mode = AddrModeFlat;

    sf.AddrStack.Offset = c.Esp;

    sf.AddrStack.Mode = AddrModeFlat;

    sf.AddrFrame.Offset = c.Ebp;

    sf.AddrFrame.Mode = AddrModeFlat;

    #elif _M_X64

    dwImageType = IMAGE_FILE_MACHINE_AMD64;

    sf.AddrPC.Offset = c.Rip;

    sf.AddrPC.Mode = AddrModeFlat;

    sf.AddrFrame.Offset = c.Rsp;

    sf.AddrFrame.Mode = AddrModeFlat;

    sf.AddrStack.Offset = c.Rsp;

    sf.AddrStack.Mode = AddrModeFlat;

    #elif _M_IA64

    dwImageType = IMAGE_FILE_MACHINE_IA64;

    sf.AddrPC.Offset = c.StIIP;

    sf.AddrPC.Mode = AddrModeFlat;

    sf.AddrFrame.Offset = c.IntSp;

    sf.AddrFrame.Mode = AddrModeFlat;

    sf.AddrBStore.Offset = c.RsBSP;

    sf.AddrBStore.Mode = AddrModeFlat;

    sf.AddrStack.Offset = c.IntSp;

    sf.AddrStack.Mode = AddrModeFlat;

    #else

    #error "Platform not supported!"

    #endif

     

    HANDLE hThread = GetCurrentThread();

    vector<CallStackInfo> arrCallStackInfo;

     

    while (true)

    {

    // 该函数是实现这个功能的最重要的一个函数

    // 函数的用法以及参数和返回值的具体解释可以查询MSDN

    //

    if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))

    {

    break;

    }

     

    if (sf.AddrFrame.Offset == 0)

    {

    break;

    }

     

    CallStackInfo callstackinfo;

            memset(&callstackinfo, 0, sizeof(callstackinfo));

     

    BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH];

     

    IMAGEHLP_SYMBOL64 *pSymbol = (IMAGEHLP_SYMBOL64*)symbolBuffer;

    memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH);

    pSymbol->SizeOfStruct = sizeof(symbolBuffer);

    pSymbol->MaxNameLength = MAX_NAME_LENGTH;

     

    DWORD symDisplacement = 0;

     

    // 得到函数名

    //

    if (SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, NULL, pSymbol))

    {

                strncpy_s(callstackinfo.MethodName, MAX_NAME_LENGTH, pSymbol->Name, _TRUNCATE);

    }

     

    IMAGEHLP_LINE64 lineInfo;

    memset(&lineInfo, 0, sizeof(IMAGEHLP_LINE64));

    lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

     

    DWORD dwLineDisplacement;

     

    // 得到文件名和所在的代码行

    //

    if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))

    {

                strncpy_s(callstackinfo.FileName, MAX_NAME_LENGTH, lineInfo.FileName, _TRUNCATE);

    sprintf_s(callstackinfo.LineNumber, "%d", lineInfo.LineNumber);

    }

     

    IMAGEHLP_MODULE64 moduleInfo;

    memset(&moduleInfo, 0, sizeof(IMAGEHLP_MODULE64));

    moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);

     

    // 得到模块名

    //

    if (SymGetModuleInfo64(hProcess, sf.AddrPC.Offset, &moduleInfo))

    {

    strncpy_s(callstackinfo.ModuleName, MAX_NAME_LENGTH, moduleInfo.ModuleName, _TRUNCATE);

    }

     

    arrCallStackInfo.push_back(callstackinfo);

    }

     

    SymCleanup(hProcess);

     

    return arrCallStackInfo;

    }

     

    // 创建Dump文件

    //

    void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)

    {

    // 创建Dump文件

    //

    HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

        if (INVALID_HANDLE_VALUE != hDumpFile)

        {

            // Dump信息

            //

            MINIDUMP_EXCEPTION_INFORMATION dumpInfo;

            dumpInfo.ExceptionPointers = pException;

            dumpInfo.ThreadId = GetCurrentThreadId();

            dumpInfo.ClientPointers = TRUE;

     

            // 写入Dump文件内容

            //

            MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

     

            CloseHandle(hDumpFile);

        }

    }

     

     

    void PrintExceptionStackInfo(EXCEPTION_POINTERS *pException)

    {

        // 确保有足够的栈空间

    //

    #ifdef _M_IX86

    if (pException->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)

    {

    static char TempStack[1024 * 128];

    __asm mov eax,offset TempStack[1024 * 128];

    __asm mov esp,eax;

    }

    #endif

     

    // 输出Crash信息 // 崩溃信息

    //

        cout << setbase(16) << setiosflags(ios::uppercase);

        cout << "ErrorCode: " << pException->ExceptionRecord->ExceptionCode << endl;

        cout << "Address : " << pException->ExceptionRecord->ExceptionAddress << endl;

    cout << "Flags : " << pException->ExceptionRecord->ExceptionFlags << endl;

        cout << endl;

     

     

    vector<CallStackInfo> arrCallStackInfo = GetCallStack(pException->ContextRecord);

     

    // 输出CallStack

    //

        cout << "*********************CallStack********************" << endl;

    for (vector<CallStackInfo>::iterator it = arrCallStackInfo.begin(); it != arrCallStackInfo.end(); ++it)

    {

    CallStackInfo callstackinfo = (*it);

            cout << callstackinfo.MethodName << "() , " << "@line:" << callstackinfo.LineNumber<< " [" << callstackinfo.ModuleName << "]" << endl;

            cout << " (File: " << callstackinfo.FileName << ")" << endl;

    }

    }

     

    // 处理Unhandled Exception的回调函数

    //

    LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)

    {

        //CreateDumpFile(_T("E:\ExceptionDump.dmp"), pException);

        PrintExceptionStackInfo(pException);

     

        // 这里弹出一个错误对话框并退出程序

    //

    //FatalAppExit(-1, _T("*** Unhandled Exception! ***"));

        printf("*** Unhandled Exception! *** ");

     

    return EXCEPTION_EXECUTE_HANDLER;

    }

     

    // 一个有函数调用的类

    //

    void TestCrash()

    {

    // 除零,人为的使程序崩溃

    //

    int i = 13;

    int j = 0;

    int m = i / j;

        printf("%d", m);

    }

     

     

    int main(int argc, _TCHAR* argv[])

    {

        SetCurrentDirectoryA("E:\test2010\ExceptionDump");

     

    // 设置处理Unhandled Exception的回调函数

    //

    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);

     

    TestCrash();

     

    return 0;

    }

  • 相关阅读:
    【BZOJ4864】[BeiJing 2017 Wc]神秘物质 Splay
    【BZOJ3438】小M的作物 最小割
    【BZOJ3436】小K的农场 差分约束
    【BZOJ2879】[Noi2012]美食节 动态加边网络流
    【BZOJ1070】[SCOI2007]修车 费用流
    【BZOJ1486】[HNOI2009]最小圈 分数规划
    搜索ABAP程序代码中的字符串
    自定义表的维护
    用户名转换成中文名
    日期计算
  • 原文地址:https://www.cnblogs.com/ant-wjf/p/7020266.html
Copyright © 2020-2023  润新知