目錄
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調試軟件。