Win10 Qt5.12.2 + MSVC編譯器 dump文件創建與分析

 

目錄

 

1. 概要

2. 研究目的

3. Qt+MSVC環境配置

3.1. 安裝Qt

3.2. 安裝VS或者安裝對應版本的編譯器

4. dump文件生成

4.1  Qt 生成dump文件的代碼

5. Qt dump調試的原材料:pdb文件

6. 調試

6.1 使用VS調試

6.2 使用WinDbg調試

6.2.1 安裝Windows Debugging Tools

6.2.2 調試


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

6.2.2 調試

參考:https://www.cnblogs.com/nchxmoon/p/4390980.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章