QT Mingw编译通过Dump文件查看源码报错的位置
文件中创建并生成Dump文件¶
使用以下代码创建并生成Dump文件
#include <windows.h>
#include <dbghelp.h>
#include <QDateTime>
#include <QMessageBox>
#include <QTextCodec>
LONG CreateCrashHander(EXCEPTION_POINTERS *pException)
{
if (!pException) { // 防止空指针崩溃
QMessageBox::warning(NULL, "错误", "异常指针为空!", QMessageBox::Ok);
return EXCEPTION_CONTINUE_SEARCH;
}
// 获取应用程序工作目录路径(程序运行时所在的目录)
QString appWorkPath = QCoreApplication::applicationDirPath();
// 1. 生成合法的文件名(不含非法字符)
QDateTime CurrentDTime = QDateTime::currentDateTime();
QString CurrentDtimeStr = CurrentDTime.toString("yyyy-MM-dd hh-mm-ss"); // 用-替代:
// 获取用户文档目录(确保有写入权限)
QString dumpText = appWorkPath + "/Dump_" + CurrentDtimeStr + ".dmp"; // 完整路径
// 2. 创建文件(显式使用宽字符版本CreateFileW)
HANDLE DumpHandle = CreateFileW(
(LPCWSTR)dumpText.utf16(), // 宽字符路径
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
// 3. 处理文件创建失败的情况
if (DumpHandle == INVALID_HANDLE_VALUE) {
DWORD errorCode = GetLastError(); // 获取系统错误代码
QMessageBox::critical(NULL, "创建dump失败",
QString("无法创建dump文件!\n路径:%1\n错误代码:%2")
.arg(dumpText).arg(errorCode),
QMessageBox::Ok);
return EXCEPTION_EXECUTE_HANDLER;
}
// 4. 生成minidump(使用更完整的类型)
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pException;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = TRUE;
// 调用MiniDumpWriteDump生成dump
BOOL success = MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
DumpHandle,
MiniDumpWithFullMemory, // 包含完整内存信息
&dumpInfo,
NULL,
NULL
);
if (!success) {
QMessageBox::warning(NULL, "生成dump失败",
QString("MiniDumpWriteDump调用失败!错误代码:%1")
.arg(GetLastError()),
QMessageBox::Ok);
}
CloseHandle(DumpHandle); // 关闭文件句柄
// 5. 显示崩溃信息
EXCEPTION_RECORD *record = pException->ExceptionRecord;
QString errCode = QString::number(record->ExceptionCode, 16).toUpper();
QString errAddr = QString::number((quint64)record->ExceptionAddress, 16).toUpper();
QString errFlag = QString::number(record->ExceptionFlags, 16).toUpper();
QString errPara = QString::number(record->NumberParameters, 16).toUpper();
QMessageBox::warning(NULL, "程序崩溃",
QString("错误代码:0x%1\n错误地址:0x%2\n错误标志:0x%3\n参数数量:0x%4\nDump文件已保存至:%5")
.arg(errCode).arg(errAddr).arg(errFlag).arg(errPara).arg(dumpText),
QMessageBox::Ok);
return EXCEPTION_EXECUTE_HANDLER;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QTextCodec *codec=QTextCodec::codecForLocale();
QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CreateCrashHander);
for(int i=10;i>=0;i--){
int a = 10/i;
}
w.show();
return a.exec();
}
代码想要运行还需要再pro文件中增加相关lib库
为了生成的代码能够输出调试信息,在pro文件中增加以下内容
代码编译如果崩溃,就会在目录下生成dump文件
后面release试了以下
# ========== 调试信息配置 ==========
# Debug 模式:默认有 -g,不动
# Release 模式:额外加上 -g,同时保留优化
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -O2 -g
# 避免 Release 链接时 strip 掉符号
QMAKE_LFLAGS_RELEASE -= -s
# MSVC 下也强制生成 PDB(Release 模式)
win32-msvc* {
QMAKE_CXXFLAGS_RELEASE += /Zi
QMAKE_LFLAGS_RELEASE += /DEBUG /INCREMENTAL:NO
}
后面发现好像不用这么麻烦,用下面指令就行了,但是带上debuginfo的应用程序会大很多。
查看错误信息¶
addr2line¶
源代码不能改,改了就和生成的错误信息对不上了。
你在 Windows + MinGW + Qt 下,生成的 dump 文件里会有崩溃地址(ExceptionAddress)。 例如:
这时就可以用 addr2line 去查源码位置:
输出可能是:
表示崩溃发生在 main.cpp 第 42 行。
-
你的程序必须是 带调试信息编译的(
-g选项)。
在 Qt 项目的.pro文件里可以加:QMAKE_CXXFLAGS += -g -
不要去掉符号(也就是不要加
-sstrip)。
gdb¶
输入gdb加上应用程序名字
然后使用list查看