C++全局异常捕获和分析.dmp文件

C++全局异常捕获和调试.dmp文件

​ 在c++的程序运行过程中,有时需要分析异常产生的原因,所以首先需要捕获异常,生成crash文件(.dmp)之后,再用相关的调试工具去分析。

如何捕获异常,生成文件保存到本地?

先上代码:

#ifndef CRASH_EXCEPTION_H
#define CRASH_EXCEPTION_H

/**********************************************************************
 *@projectName    CrashTest
 *@brief          windows捕获全局异常写本地dump文件
 *Author:         zlozl
 *Copyright:      zlozl
 *Email:          zlozl5566@163.com
 *QQ:             849414798
 *BlogAddress:    https://blog.youkuaiyun.com/ZLOZL
 *GiteeHome:      https://gitee.com/zlozl5566
 *Version:        V1.0.0.1
 *Create Date:    2021-03-31
**********************************************************************/
/*
****************************************************************************************************
* windows平台建议选择MSVC编译器,可以用vs定位到出错代码行
****************************************************************************************************
*/

#ifdef  _WIN32
#include <TCHAR.h>
#include "Windows.h"
#include "DbgHelp.h"

int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
    // 定义函数指针
    typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
        HANDLE,
        DWORD,
        HANDLE,
        MINIDUMP_TYPE,
        PMINIDUMP_EXCEPTION_INFORMATION,
        PMINIDUMP_USER_STREAM_INFORMATION,
        PMINIDUMP_CALLBACK_INFORMATION
        );
    // 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
    MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
    HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
    if (NULL == hDbgHelp)
    {
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");

    if (NULL == pfnMiniDumpWriteDump)
    {
        FreeLibrary(hDbgHelp);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    // 创建 dmp 文件
    TCHAR szFileName[MAX_PATH] = { 0 };
    SYSTEMTIME stLocalTime;
    GetLocalTime(&stLocalTime);
    swprintf(szFileName, L"crash_%04d%02d%02d-%02d%02d%02d.dmp",
        stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
        stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
    HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
    if (INVALID_HANDLE_VALUE == hDumpFile)
    {
        FreeLibrary(hDbgHelp);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    // 写入 dmp 文件
    MINIDUMP_EXCEPTION_INFORMATION expParam;
    expParam.ThreadId = GetCurrentThreadId();
    expParam.ExceptionPointers = pExceptionPointers;
    expParam.ClientPointers = FALSE;
    pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
        hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
    // 释放文件
    CloseHandle(hDumpFile);
    FreeLibrary(hDbgHelp);
    return EXCEPTION_EXECUTE_HANDLER;
}

LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
    // 这里做一些异常的过滤或提示
    if (IsDebuggerPresent())
    {
        return EXCEPTION_CONTINUE_SEARCH;
    }
    return GenerateMiniDump(lpExceptionInfo);
}

#endif //  _WIN32

#endif // CRASH_EXCEPTION_H

测试示例:

#include "crash_exception.h"

int main()
{
    // 加入崩溃dump文件功能
    SetUnhandledExceptionFilter(ExceptionFilter);
    // 使程序崩溃产生 Dump 文件
    int *p = NULL;
    *p = 1;
}

结果产生了crash文件。

在这里插入图片描述

如何分析crash文件?

​ 通过Visual Studio工具可以分析,只需把.dmp文件托到编译器中,设置符号路径。

在这里插入图片描述

添加一下.pdb符号文件的路径,注意dump文件,程序编译生成的pdb文件(版本必须是产生崩溃的那个版本的编译信息),可执行文件(发生崩溃的版本)。如上图crash文件标志所示。

在这里插入图片描述

然后点击使用本机调试,就会跳转到产生异常的行数。

在这里插入图片描述

<think>好的,我需要帮用户解决在Linux环境下使用Qt实现全局异常捕获,并确保跨平台的问题。首先,我得回忆一下Qt相关的异常处理机制。Qt本身主要处理的是应用层的异常,比如信号槽的错误,但对于系统级别的崩溃,比如段错误或访问违规,可能没有直接的支持。这时候通常需要借助第三方库或者系统API来实现。 用户提到了跨平台,所以不能只考虑Linux的方案,还要兼容WindowsmacOS。Breakpad是Google开发的一个跨平台崩溃报告工具,被很多项目使用,比如ChromeFirefox。看起来Breakpad是个不错的选择。之前有看到Qt项目中集成Breakpad的案例,比如引用[2]提到的,使用Breakpad可以实现跨平台的崩溃捕获,生成dump文件,然后分析这些文件来定位问题。 接下来,我需要考虑如何在Qt工程中集成Breakpad。通常步骤包括下载Breakpad源码,编译生成静态库,然后在Qt项目中链接这些库。在代码中初始化Breakpad的异常处理程序,这样当崩溃发生时,Breakpad会捕获并生成minidump文件。这部分需要详细说明编译配置的步骤,确保用户能够正确操作。 另外,用户可能还需要处理生成的dump文件,比如上报分析。这里需要提到如何将dump文件转换为可读的堆栈跟踪信息,可能需要使用Breakpad提供的工具,比如dump_symsminidump_stackwalk。同时,要确保这些步骤在跨平台环境中可行,可能需要针对不同平台进行一些调整,但Breakpad本身已经处理了大部分跨平台兼容性问题。 还要考虑Qt的信号处理机制。虽然Breakpad能处理系统级别的异常,但Qt应用中的异常可能需要结合try-catch块Qt的信号处理,比如重写QApplication的notify方法,或者在main函数中设置信号处理函数。不过,对于C++异常(如std::exception),Breakpad可能无法直接捕获,需要结合SEH(Windows)或信号处理(Linux/macOS)来实现。 总结下来,解决方案的核心是使用Breakpad进行跨平台的崩溃捕获,生成dump文件,并结合Qt的信号处理机制来完善异常捕获。需要详细指导用户如何编译Breakpad、集成到Qt项目、初始化异常处理程序,以及后续的dump文件处理步骤。同时,提醒用户注意不同平台的编译差异,确保跨平台兼容性,并建议结合日志系统以便更全面地分析问题。</think>在Linux环境下使用Qt实现全局异常捕获并确保跨平台兼容性,可通过以下分步实现方案完成: ### 一、跨平台异常捕获方案选择 推荐使用**Google Breakpad**实现跨平台崩溃捕获,其支持Linux/Windows/macOS三平台,可生成标准minidump文件[^2]。该方案与Qt集成度高,已有多个开源项目验证其稳定性。 ### 二、具体实现步骤 #### 1. 编译Breakpad库 ```bash # 下载源码 git clone https://github.com/google/breakpad.git cd breakpad # 生成编译配置 ./configure # 编译(Linux示例) make -j4 # 生成静态库文件: src/client/linux/libbreakpad_client.a src/tools/linux/dump_syms/dump_syms ``` #### 2. Qt工程集成 ```pro # Qt项目文件(.pro)添加配置 INCLUDEPATH += $$PWD/breakpad/src LIBS += -L$$PWD/breakpad/src/client/linux -lbreakpad_client \ -lpthread ``` #### 3. 初始化异常处理器 ```cpp #include "client/linux/handler/exception_handler.h" static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) { qDebug() << "Dump generated:" << descriptor.path(); return succeeded; } int main(int argc, char *argv[]) { google_breakpad::MinidumpDescriptor descriptor("/tmp"); google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1); QApplication a(argc, argv); // 应用程序初始化 return a.exec(); } ``` #### 4. 异常信号处理增强(Linux专用) ```cpp #include <execinfo.h> #include <signal.h> void stackTraceHandler(int sig) { void* array[50]; size_t size = backtrace(array, 50); fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, STDERR_FILENO); exit(1); } // 在main函数中注册信号 signal(SIGSEGV, stackTraceHandler); signal(SIGABRT, stackTraceHandler); ``` ### 三、跨平台兼容性处理 1. **Windows适配**:需编译`exception_handler_win.cc`,使用`DBGHELP.DLL`生成dump 2. **macOS适配**:需使用`client/mac`目录下的实现,注意处理Mach异常 3. **统一接口封装**: ```cpp class CrashHandler { public: #if defined(Q_OS_WIN) using ExceptionHandler = google_breakpad::ExceptionHandlerWin; #elif defined(Q_OS_MAC) using ExceptionHandler = google_breakpad::ExceptionHandlerMac; #else using ExceptionHandler = google_breakpad::ExceptionHandlerLinux; #endif }; ``` ### 四、崩溃文件分析流程 1. 使用`dump_syms`生成符号文件: ```bash dump_syms ./MyApp > MyApp.sym ``` 2. 解析minidump: ```bash minidump_stackwalk xxx.dmp ./symbols > crash_log.txt ``` ### 五、注意事项 1. **发布版本保留调试符号**:建议同时发布带调试符号的版本 2. **文件路径权限**:确保dump保存目录有写权限 3. **Qt事件循环异常**:建议重写`QApplication::notify()`捕获未处理异常 ```cpp bool MyApplication::notify(QObject* receiver, QEvent* event) { try { return QApplication::notify(receiver, event); } catch (const std::exception& e) { qCritical() << "Unhandled exception:" << e.what(); } return false; } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZLOZL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值