标签 死机报告 下的文章

C++ | window下生成dump文件的死机报告解决程序异常崩溃


代码部分

依赖库 DbgHelp

win下直接链接引入即可: target_link_libraries(${PROJECT_NAME} DbgHelp)

头文件引入

#include <DbgHelp.h>

win异常处理函数注册

#ifdef WIN32
    // 注册异常处理函数
    LPTOP_LEVEL_EXCEPTION_FILTER Top = SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
    // 此函数与搜狗输入法冲突,会导致编译不过或程序运行崩溃
    // DisableSetUnhandledExceptionFilter();
#endif

异常处理执行函数代码如下

#ifdef WIN32
// 崩溃相关处理函数
LONG WINAPI ApplicationCrashHandler(EXCEPTION_POINTERS *pException){


    //这里弹出一个错误对话框并退出程序
    EXCEPTION_RECORD* record = pException->ExceptionRecord;


    QString errCode(QString::number((uint)record->ExceptionCode,16)),
            errAdr(QString::number(PtrToInt(record->ExceptionAddress),16)), 
            errMod;


    // 崩溃日志写入
    LOG_ERROR(QString::fromLocal8Bit("错误代码:%1 错误地址:%2").arg(errCode).arg(errAdr).toStdString().c_str());


    // 创建错误文件
    HANDLE dumpFile = CreateFile((LPCWSTR)QString("./error.dmp").utf16(),GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(dumpFile != INVALID_HANDLE_VALUE)
    {
        MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
        dumpInfo.ExceptionPointers = pException;
        dumpInfo.ThreadId = GetCurrentThreadId();
        dumpInfo.ClientPointers = TRUE;


        MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
        CloseHandle(dumpFile);
        LOG_INFO(QString::fromLocal8Bit("调试信息生成成功。").toStdString().c_str());
    }else{
        LOG_ERROR(QString::fromLocal8Bit("调试信息文件生成失败。").toStdString().c_str());
    }


    QMessageBox::critical(NULL,
                          QString::fromLocal8Bit("程式崩溃"),
                          QString::fromLocal8Bit("<FONT size=4><div><b>对于发生的错误,表示诚挚的歉意</b><br/></div>")+
                          QString::fromLocal8Bit("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
                          QMessageBox::Ok);


    //EXCEPTION_EXECUTE_HANDLER
    return EXCEPTION_EXECUTE_HANDLER;
    // return EXCEPTION_CONTINUE_EXECUTION;
}


//防止CRT(C runtime)函数报错可能捕捉不到,这里与搜狗输入法存在bug,回到这程序起不来(暂时不执行此函数)
void DisableSetUnhandledExceptionFilter()
{
    void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"), "SetUnhandledExceptionFilter");
    if(addr)
    {
        unsigned char code[16];
        int size = 0;


        code[size++] = 0x33;
        code[size++] = 0xC0;
        code[size++] = 0xC2;
        code[size++] = 0x04;
        code[size++] = 0x00;


        DWORD dwOldFlag, dwTempFlag;
        VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
        WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
        VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
    }
}
#endif

文件处理过程

在程序崩溃后会在指定目录下生成dmp文件(代码内指定了./error.dmp),正常在根目录找到error.dmp文件拖拽到visual studio中,右侧红框内可选择对应pdb进行调试。
65af2c1c92e38.png