ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Qt发布的window程序运行过程中出错定位方法

Qt发布的window程序运行过程中出错定位方法 一、生成Dump文件在Windows上生成Dump文件(内存转储文件)主要有以下几种方法,适用于不同场景。1、任务管理器生成Dump文件1)打开任务管理器(Ctrl+Shift+Esc)2)在“详细信息”选项卡中找到目标进程3)右键点击进程 → “创建转储文件”4)文件默认保存在:%temp%\进程名.dmp2、使用Procdump工具(微软官方推荐)下载安装从微软官网下载Procdump:https://learn.microsoft.com/en-us/sysinternals/downloads/procdump常用命令示例cmd# 1. 立即生成进程的完整Dump procdump -ma PID 或 procdump -ma 进程名 # 2. 当CPU使用率超过阈值时生成Dump procdump -ma -c 90 -s 10 进程名 # 3. 监控异常并生成Dump procdump -ma -e 1 进程名 # 4. 连续生成多个Dump procdump -ma -n 5 进程名 # 5. 带时间戳的文件名 procdump -ma -s 10 -n 3 -d 进程名3、C/C++ 代码生成Dump使用MiniDumpWriteDump API生成dump文件。minidump.h#ifndef MINIDUMP_H #define MINIDUMP_H #include QString #include windows.h #include dbghelp.h #pragma comment(lib, "dbghelp.lib") class MiniDumpGenerator { public: static void initialize(); static void setDumpPath(const QString path); static QString generateDumpFileName(); private: static LONG WINAPI unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); static void createMiniDump(PEXCEPTION_POINTERS pExceptionInfo); static QString dumpPath; }; #endif // MINIDUMP_Hminidump.cpp#include "minidump.h" #include QDateTime #include QDir #include QCoreApplication #include QDebug QString MiniDumpGenerator::dumpPath = ""; LONG WINAPI MiniDumpGenerator::unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { qCritical() "发生未处理异常,正在生成dump文件..."; createMiniDump(pExceptionInfo); // 返回 EXCEPTION_EXECUTE_HANDLER 会终止程序 // 返回 EXCEPTION_CONTINUE_SEARCH 会让系统显示错误对话框 return EXCEPTION_EXECUTE_HANDLER; } void MiniDumpGenerator::createMiniDump(PEXCEPTION_POINTERS pExceptionInfo) { QString fileName = generateDumpFileName(); HANDLE hFile = CreateFileW( fileName.toStdWString().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { qWarning() "无法创建dump文件:" GetLastError(); return; } MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; exceptionInfo.ThreadId = GetCurrentThreadId(); exceptionInfo.ExceptionPointers = pExceptionInfo; exceptionInfo.ClientPointers = TRUE; // 生成完整的dump文件 BOOL success = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)( // 添加类型转换 MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | MiniDumpWithDataSegs ), exceptionInfo, NULL, NULL); if (success) { qDebug() "Dump文件已生成:" fileName; // 创建对应的日志文件 QString logFile = fileName; logFile.replace(".dmp", ".log"); QFile file(logFile); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(file); out "崩溃时间: " QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz") "\n"; out "应用程序: " QCoreApplication::applicationName() "\n"; out "版本: " QCoreApplication::applicationVersion() "\n"; out "异常代码: 0x" QString::number(pExceptionInfo-ExceptionRecord-ExceptionCode, 16) "\n"; out "异常地址: 0x" QString::number((ULONG_PTR)pExceptionInfo-ExceptionRecord-ExceptionAddress, 16) "\n"; file.close(); } } else { qWarning() "生成dump文件失败:" GetLastError(); } CloseHandle(hFile); } QString MiniDumpGenerator::generateDumpFileName() { QString path = dumpPath; if (path.isEmpty()) { path = QCoreApplication::applicationDirPath() + "/dumps"; } QDir dir(path); if (!dir.exists()) { dir.mkpath("."); } QString appName = QCoreApplication::applicationName(); if (appName.isEmpty()) { appName = "application"; } QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss_zzz"); return QString("%1/%2_%3.dmp").arg(path).arg(appName).arg(timestamp); } void MiniDumpGenerator::initialize() { // 设置未处理异常过滤器 SetUnhandledExceptionFilter(unhandledExceptionHandler); // 禁用Windows错误报告对话框 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); } void MiniDumpGenerator::setDumpPath(const QString path) { dumpPath = path; }Qt Creator 集成配置在.pro文件中添加:# .pro 文件配置 QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 # 调试信息 win32 { CONFIG(debug, debug|release) { # 生成调试信息 QMAKE_CXXFLAGS += /Zi QMAKE_LFLAGS += /DEBUG # 生成 PDB 文件 QMAKE_LFLAGS += /PDB:$${TARGET}.pdb } # 添加 dump 生成支持 HEADERS += minidump.h SOURCES += minidump.cpp }在main.cpp中初始化:// main.cpp #include QApplication #include "minidump.h" int main(int argc, char *argv[]) { // 初始化 dump 生成器 MiniDumpGenerator::initialize(); MiniDumpGenerator::setDumpPath("C:/AppDumps"); // 可选 QApplication app(argc, argv); // 设置应用信息 app.setApplicationName("MyApp"); app.setApplicationVersion("1.0.0"); // ... 应用程序代码 return app.exec(); }MiniDump(添加堆栈信息打印功能)类// minidump_enhanced.h #ifndef MINIDUMP_ENHANCED_H #define MINIDUMP_ENHANCED_H #include QString #include QVector #include QDateTime #include windows.h #include dbghelp.h #include QCoreApplication #pragma comment(lib, "dbghelp.lib") class MiniDumpEnhanced { public: struct StackFrame { QString moduleName; QString functionName; QString fileName; int lineNumber; DWORD64 address; DWORD64 offset; QString symbolName; }; struct ExceptionInfo { DWORD exceptionCode; QString exceptionDescription; DWORD64 exceptionAddress; QVectorStackFrame callStack; QDateTime crashTime; QString dumpFilePath; }; // 初始化选项 struct InitOptions { bool enableStackTrace = true; // 启用堆栈跟踪 int maxStackFrames = 100; // 最大堆栈帧数 bool captureFullMemory = false; // 是否捕获完整内存 bool saveToFile = true; // 是否保存到文件 QString customDumpPath; // 自定义dump路径 QString customReportPath; // 自定义报告路径 }; // 初始化dump捕获 static void initialize(const InitOptions options = InitOptions()); // 手动生成dump(用于测试或特定情况) static QString generateMiniDump(bool withStackTrace = true, const QString reason = ""); // 获取最近一次崩溃信息 static ExceptionInfo getLastExceptionInfo(); // 获取堆栈跟踪字符串 static QString getStackTraceString(); // 设置回调函数(可选) typedef void (*CrashCallback)(const ExceptionInfo info); static void setCrashCallback(CrashCallback callback); // 测试函数(生成测试崩溃) static void testCrash(int type = 0); private: static LONG WINAPI exceptionHandler(PEXCEPTION_POINTERS exceptionInfo); static void createMiniDump(PEXCEPTION_POINTERS exceptionInfo); static void captureStackTrace(PEXCEPTION_POINTERS exceptionInfo); static QString generateStackTrace(PEXCEPTION_POINTERS exceptionInfo); static QVectorStackFrame walkStack(PEXCEPTION_POINTERS exceptionInfo); static QString generateDumpFileName(); static QString generateReportFileName(const QString dumpFile); static void writeCrashReport(const QString dumpFile, PEXCEPTION_POINTERS exceptionInfo, const QString stackTrace); static void cleanupOldDumps(int keepDays = 7); static InitOptions options; static ExceptionInfo lastException; static CrashCallback crashCallback; static bool initialized; }; #endif // MINIDUMP_ENHANCED_H// minidump_enhanced.cpp #include "minidump_enhanced.h" #include QDir #include QFile #include QTextStream #include QDebug #include QProcess #include QThread #include memory #include sstream #include iomanip // 初始化静态成员 MiniDumpEnhanced::InitOptions MiniDumpEnhanced::options; MiniDumpEnhanced::ExceptionInfo MiniDumpEnhanced::lastException; MiniDumpEnhanced::CrashCallback MiniDumpEnhanced::crashCallback = nullptr; bool MiniDumpEnhanced::initialized = false; // 符号信息结构 struct SymbolInfo { SYMBOL_INFO symbol; char nameBuffer[256]; }; // 异常代码描述映射 static const std::unordered_mapDWORD, QString exceptionDescriptions = { {EXCEPTION_ACCESS_VIOLATION, "访问违规 (Access Violation)"}, {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "数组边界超出"}, {EXCEPTION_BREAKPOINT, "断点异常"}, {EXCEPTION_DATATYPE_MISALIGNMENT, "数据类型未对齐"}, {EXCEPTION_FLT_DENORMAL_OPERAND, "浮点异常: 非正规操作数"}, {EXCEPTION_FLT_DIVIDE_BY_ZERO, "浮点除以零"}, {EXCEPTION_FLT_INEXACT_RESULT, "浮点不精确结果"}, {EXCEPTION_FLT_INVALID_OPERATION, "浮点无效操作"}, {EXCEPTION_FLT_OVERFLOW, "浮点上溢"}, {EXCEPTION_FLT_STACK_CHECK, "浮点栈检查"}, {EXCEPTION_FLT_UNDERFLOW, "浮点下溢"}, {EXCEPTION_ILLEGAL_INSTRUCTION, "非法指令"}, {EXCEPTION_IN_PAGE_ERROR, "页面错误"}, {EXCEPTION_INT_DIVIDE_BY_ZERO, "整数除以零"}, {EXCEPTION_INT_OVERFLOW, "整数溢出"}, {EXCEPTION_INVALID_DISPOSITION, "无效处置"}, {EXCEPTION_NONCONTINUABLE_EXCEPTION, "不可继续的异常"}, {EXCEPTION_PRIV_INSTRUCTION, "特权指令"}, {EXCEPTION_SINGLE_STEP, "单步执行"}, {EXCEPTION_STACK_OVERFLOW, "栈溢出"}, {0xC0000409, "堆栈缓冲区溢出 (Stack Buffer Overrun)"}, {0xE06D7363, "Microsoft C++ 异常"} }; LONG WINAPI MiniDumpEnhanced::exceptionHandler(PEXCEPTION_POINTERS exceptionInfo) { qCritical
返回列表