目录
6.2.1 安装Windows Debugging Tools
1. 概要
本文主要研究dump文件在windows操作系统、Qt编辑器、MSVC编译环境下的产生和分析。主要从以下几个方面来描述:
1. dump文件存在的意义;
2. 配置Win10操作系统下, QT + MSVC的编写编译环境;
3. dump文件如何产生;
4. windows 软件分析调试dump文件的必备材料:pdb文件;
5. 分析和调试方法;
2. 研究目的
为什么需要研究dump文件分析?
软件在长时间运行后,突然崩溃或死掉,且此时的日志也未写入或者日志中无法提示任何信息。此时我们就需要分析dump文件,判断崩溃时的堆栈,以及断点调试查看相关的值,进而了解到软件的不健壮节点并加以修复。
3. Qt+MSVC环境配置
尽量采用Qt自检测编译的方式来加载MSCV编译器。
3.1. 安装Qt
在安装Qt时,需要注意我们安装的kit版本,我的Qt版本是Qt5.12.2,选择安装的Kit有 Qt 5.12.2 MSVC2015 64bit、Qt 5.12.2 MSVC2017 32bit、Qt 5.12.2 MinGW 32-bit、 Qt 5.12.2 MinGW 64-bit。安装完成后,在Qt->工具->选项->Kits里看到安装的Kit套件。在安装完成后,可以选择将编译器所在的路径添加到环境变量。
3.2. 安装VS或者安装对应版本的编译器
因为在安装Qt时选择的kit中有Qt 5.12.2 MSVC2017 32bit,所以我选择安装VS的版本也是2017版本(ps:之前有安装2019版本,结果Qt不能自然搜索到对应的编译器,应该是Qt5.12.2无法检测到VS2019的编译器,当然,我们也可以在Qt中自定义个编译器,本文暂不做阐释)。选择安装的内容,包含 “使用C++的桌面开发”,“通用Windows平台开发”。
3. 配置Qt的MSVC的环境
在安装VS完成后,重启下Qt,会在Qt->工具->选项->Kits看到对应的编译器。
然后,将构建套件kit相应项配置编译器和调试器。微软的配置微软的编译器。
至此,Qt5.12 + MSVC编译环境就配置完成了。
4. dump文件生成
4.1 Qt 生成dump文件的代码
#include <Windows.h>
#include <DbgHelp.h>
#pragma comment(lib, "user32.lib")
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 };
TCHAR szVersion[] = L"DumpFile";
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
szVersion, 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);
}
调用代码:
int main(int argc, char *argv[])
{
//生成异常的dump文件
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
QApplication a(argc, argv);
CoreDumpWin w;
w.show();
return a.exec();
}
至此,软件运行过程中,如果异常崩溃,会产出.dmp文件。
5. Qt dump调试的原材料:pdb文件
如果应用或服务产生pdb文件,只需要在项目构建的qmake添加额外的参数:
CONFIG+=force_debug_info" "CONFIG+=separate_debug_info"
Qt自身模块pdb文件在Qt安装时,是不安装的,所以需要我们手动去安装Qt的pdb文件:
手动安装匹配的pdb文件的原文链接地址。
a)首先在qt的安装目录下找到MaintenanceTool.exe,运行它
b) 设置存储库地址,建议选择临时库,且添加地址, 测试并提醒成功,点击ok。(5122是Qt的版本号)
https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5122/
https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/tools_mingw/
https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5122_src_doc_examples/
c) 添加或移除组件,点击“下一步”。
d)选择 "Qt Debug Information Files",选择完成后,点击“下一步”,并安装。如果网速慢的话,这将是个漫长的过程。(注意:除非你想卸载什么,否则不要去掉已经打勾项)
至此,所有的配置与所需材料都已经完成。
6. 调试
编译Rlease程序,并将对应的pdb文件与应用/服务程序放到同一目录下,当软件执行出异常崩溃时,会在该目录下产生dmp文件,我们据此文件来调试堆栈,查看软件崩溃在什么地方,并调试它。
6.1 使用VS调试
调试方法:
a) 使用VS打开xxx.dmp文件,”使用本机进行调试“
b) 调试时,会显示崩溃的代码,以及对应的堆栈信息,如有提示未加载符号,需要我们手动添加符号路径。
通过堆栈,可以看到调用函数。
根据例子,可以分析出,MyTestClass对象指针为nullptr。调用函数on_pushButton_clicked()函数没有为MyTestClass对象指针分配内存。
6.2 使用WinDbg调试
WinDbg 除了可以分析软件崩溃的位置,也可以分析内存占用大,内存溢出等问题。
6.2.1 安装Windows Debugging Tools
官网下载 Win10SDK,并安装,且只安装Windows Debugging Tools,安装WinDbg调试软件。