首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 程式崩潰自動生成 Dump 文件實現方案

     編輯:關於C++

生產環境程式崩潰時,若能自動生成 MiniDump 文件,事後可用 WinDbg / Visual Studio 進行離線除錯,快速定位崩潰堆疊與變數值。本文提供基於 dbghelp.dll 的完整實現代碼,僅需在程式入口呼叫一次即可啟用。

核心代碼

#include <windows.h>
#include <dbghelp.h>
#include <tchar.h>
#pragma comment(lib, "dbghelp.lib")

LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS* pExceptionInfo) {
    // 1. 組裝 Dump 檔名:版本-日期時間-進程ID-線程ID.dmp
    TCHAR szFileName[MAX_PATH] = {0};
    TCHAR* szVersion = _T("v1.0");
    SYSTEMTIME st; GetLocalTime(&st);
    _stprintf_s(szFileName, _T("%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp"),
        szVersion, st.wYear, st.wMonth, st.wDay,
        st.wHour, st.wMinute, st.wSecond,
        GetCurrentProcessId(), GetCurrentThreadId());

    // 2. 建立檔案
    HANDLE hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
                              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return EXCEPTION_CONTINUE_SEARCH;

    // 3. 寫入 MiniDump(含完整記憶體)
    MINIDUMP_EXCEPTION_INFORMATION ei;
    ei.ThreadId = GetCurrentThreadId();
    ei.ExceptionPointers = pExceptionInfo;
    ei.ClientPointers = FALSE;

    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
                      MiniDumpWithFullMemory, &ei, NULL, NULL);

    CloseHandle(hFile);
    // getchar(); // 如需暫停觀察可取消註釋
    return EXCEPTION_EXECUTE_HANDLER;
}

啟用方式

在 main() / WinMain() 最開頭插入:

SetUnhandledExceptionFilter(TopLevelExceptionFilter);

關鍵參數說明

參數含義
MiniDumpWithFullMemory包含完整進程記憶體,體積較大但資訊最全
MiniDumpWithDataSegs僅包含資料段,體積較小
MiniDumpNormal最小集合(堆疊、模組、線程)

根據磁碟空間與隱私需求選擇適當旗標;生產環境建議 MiniDumpWithDataSegs | MiniDumpWithHandleData 平衡大小與可診斷性。

進階建議

  • 專用目錄:呼叫 CreateDirectory 將 Dump 集中存放,避免汙染工作目錄。
  • 上傳伺服器:結合 HTTP POST 自動上傳至崩潰收集平台(如 Sentry、自建 Crash Server)。
  • 符號表:發布時同步生成 .pdb 並妥善保存,否則 Dump 難以還原符號。
  • 多線程:SetUnhandledExceptionFilter 為進程級,所有線程共用;若需區分線程,可在過濾器內記錄 GetCurrentThreadId()。

驗證測試

int main() {
    SetUnhandledExceptionFilter(TopLevelExceptionFilter);
    int* p = nullptr; *p = 1; // 故意觸發 Access Violation
    return 0;
}

執行後當前目錄將出現 v1.0-20240115-143022-1234-5678.dmp,拖入 VS 或 WinDbg 即可看到崩潰堆疊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved