建立个人网站费用网络营销策略理论有哪些
qt应用程序崩溃日志和转储文件对于定位问题
- 一. DMP 文件包含的信息:
- 二. 分析 DMP 文件的主要方法:
- 三. 生成更详细的 DMP 文件:
- 四. 分析 DMP 文件的注意事项:
- 五. 实用建议:
- 六. 实战
一. DMP 文件包含的信息:
1崩溃时的调用堆栈
2内存状态
3寄存器值
4线程信息
5加载的模块信息
6系统信息
DMP(转储)文件记录了程序崩溃时的完整内存状态,对于分析崩溃原因非常有用。以下是关于 DMP 文件的详细说明:
二. 分析 DMP 文件的主要方法:
一. 使用 Visual Studio 分析
- 打开 Visual Studio
- 文件 -> 打开 -> 文件 -> 选择 .dmp 文件
- 在调试器中设置符号路径(必须有对应的 PDB 文件)
- 点击"调试"按钮开始分析
二.使用 WinDbg 分析
基本命令:
!analyze -v # 详细分析崩溃原因
k # 显示调用堆栈
~*k # 显示所有线程的调用堆栈
!threads # 显示线程信息
lm # 显示加载的模块
三. 生成更详细的 DMP 文件:
MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(
MiniDumpNormal | // 基本信息
MiniDumpWithFullMemory | // 完整内存
MiniDumpWithHandleData | // 句柄数据
MiniDumpWithThreadInfo | // 线程信息
MiniDumpWithProcessThreadData // 进程线程数据
);
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hDumpFile,
dumpType, // 使用更详细的转储类型
&dumpInfo,
NULL,
NULL
);
四. 分析 DMP 文件的注意事项:
1需要符号文件(PDB)
- 确保保存了程序的 PDB 文件
- PDB 文件版本必须与崩溃程序版本一致
- 设置正确的符号路径
2发布版本的准备工作
// 在 .pro 文件中添加
QMAKE_CXXFLAGS_RELEASE += /Zi # 生成调试信息
QMAKE_LFLAGS_RELEASE += /DEBUG /OPT:REF # 链接时包含调试信息
3常见崩溃原因分析:
- 访问违例(空指针)
- 内存损坏
- 栈溢出
- 非法内存访问
- 未处理的异常
五. 实用建议:
1.建立版本管理
- 保存每个发布版本的源码
- 保存对应的 PDB 文件
- 记录版本号和编译时间
2.添加额外信息
// 在生成 DMP 时添加自定义数据
MINIDUMP_USER_STREAM_INFORMATION userStreamInfo;
MINIDUMP_USER_STREAM userStream;
QString extraInfo = “Version: 1.0.0; Build: Debug”;
userStream.Type = CustomStreamType;
userStream.Buffer = (void*)extraInfo.toUtf8().data();
userStream.BufferSize = extraInfo.length();
userStreamInfo.UserStreamCount = 1;
userStreamInfo.UserStreamArray = &userStream;
通过正确分析 DMP 文件,你可以:
1确定崩溃的具体位置
2了解崩溃时的程序状态
3查看相关变量的值
4追踪问题的根源
这些信息对于修复程序问题非常重要,特别是在无法直接重现问题的情况下。
六. 实战
下面展示一个会崩溃的 Qt 程序示例,并说明如何生成和分析 DMP 文件。
1. 示例程序
// main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QDebug>
#include <windows.h>
#include <dbghelp.h>
#include <QDateTime>// DMP文件生成函数
LONG WINAPI createMiniDump(EXCEPTION_POINTERS* pExp)
{QString dumpPath = QCoreApplication::applicationDirPath() + "/crash_" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss") + ".dmp";HANDLE hDumpFile = CreateFileW(dumpPath.toStdWString().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hDumpFile != INVALID_HANDLE_VALUE) {MINIDUMP_EXCEPTION_INFORMATION dumpInfo;dumpInfo.ExceptionPointers = pExp;dumpInfo.ThreadId = GetCurrentThreadId();dumpInfo.ClientPointers = TRUE;// 生成更详细的DMP文件MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(MiniDumpNormal |MiniDumpWithFullMemory |MiniDumpWithHandleData |MiniDumpWithThreadInfo |MiniDumpWithProcessThreadData);MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),hDumpFile,dumpType,&dumpInfo,NULL,NULL);CloseHandle(hDumpFile);}return EXCEPTION_EXECUTE_HANDLER;
}// 故意制造崩溃的类
class CrashTest : public QMainWindow
{
public:CrashTest(){QPushButton* btn = new QPushButton("点击崩溃", this);setCentralWidget(btn);connect(btn, &QPushButton::clicked, this, &CrashTest::makeCrash);resize(200, 100);}void makeCrash(){// 方式1:空指针访问int* p = nullptr;*p = 100;// 方式2:数组越界// int arr[5];// arr[1000000] = 1;// 方式3:除零错误// int a = 0;// int b = 100 / a;}
};int main(int argc, char *argv[])
{// 设置异常处理函数SetUnhandledExceptionFilter(createMiniDump);QApplication a(argc, argv);CrashTest w;w.show();return a.exec();
}
2. 项目文件配置
# crash_test.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17
CONFIG += force_debug_info # 强制生成调试信息SOURCES += main.cpp# 添加 dbghelp 库
LIBS += -ldbghelp# 生成PDB文件的配置
QMAKE_CXXFLAGS_RELEASE += /Zi
QMAKE_LFLAGS_RELEASE += /DEBUG /OPT:REF
3. 编译和运行步骤
1.使用 Qt Creator 打开项目
2.选择 Release 模式编译
3.运行程序
4.点击"点击崩溃"按钮
5.程序会崩溃并在程序目录生成 .dmp 文件
4. DMP 文件分析步骤
1.使用 Visual Studio 分析
- 打开 Visual Studio
- 文件 -> 打开 -> 文件 -> 选择生成的 .dmp 文件
- 在"解决方案资源管理器"中设置符号路径:
- 工具 -> 选项 -> 调试 -> 符号
- 添加包含 PDB 文件的文件夹路径
- 点击"调试"按钮
- Visual Studio 会显示崩溃位置和调用堆栈
2.使用 WinDbg 分析
- 打开 WinDbg
- 文件 -> 打开崩溃转储
- 设置符号路径:.sympath+ [PDB文件路径]
- 输入命令:
!analyze -v # 查看详细崩溃信息
k # 查看调用堆栈
~*k # 查看所有线程的调用堆栈
5. 预期结果
在这个示例中,程序会因为空指针访问而崩溃。分析 DMP 文件时,你应该能看到:
1崩溃发生在 makeCrash() 函数中
2异常类型为访问违例(Access Violation)
3调用堆栈会显示从按钮点击到崩溃的完整路径
6. 注意事项
1确保保存了 PDB 文件
2Release 模式下也要生成调试信息
3分析时需要对应版本的源代码
4符号路径设置正确
这个例程提供了一个完整的崩溃捕获和分析流程。你可以通过修改 makeCrash() 函数来测试不同类型的崩溃情况。
完整项目我链接:qt-dmp
如果程序崩溃不容易复现难以短时间定位解决,希望崩溃后自动拉起进程,有几种方案可供选择。文章有点长,我会放在下一篇中介绍。