日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

向大厂看齐!为自己的程序增加自动转储的功能!

發布時間:2023/12/4 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 向大厂看齐!为自己的程序增加自动转储的功能! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果你還不清楚什么是轉儲文件,不知道什么時候需要轉儲文件,請參考轉儲文件系列文章的第一篇 —— 轉儲文件知多少。

前言

不知道各位小伙伴有沒有遇到過 微信 或者 QQ 崩潰的情況。它們在崩潰的時候都會自動彈出一個對話框,提示用戶上傳相關文件,供開發人員分析問題的原因。有的小伙伴兒可能不太清楚我在說什么。沒關系,下圖就是微信崩潰后自動彈出的界面。

微信 Crash Report 界面

如果勾選了 發送錯誤報告(S) 按鈕,點擊 確定(O) 按鈕后,會把收集到的文件上傳給開發人員。同樣的,如果勾選了 重啟程序(R),點擊 確定(O) 按鈕后,微信會自動重啟。有沒有覺得很酷?我們自己的程序可以做到類似的效果嗎?答案是肯定的。如果感興趣,就請繼續閱讀吧!

MiniDumpWriteDump

微軟提供了專門的 API 來生成轉儲文件,這個 API 就是 MiniDumpWriteDump()。

BOOL MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,PMINIDUMP_CALLBACK_INFORMATION CallbackParam );

簡單介紹下每個參數:

  • hProcess:要轉儲的進程句柄。

    打開進程的時候,至少需要指定 PROCESS_QUERY_INFORMATION 和 PROCESS_VM_READ 權限。如果需要轉儲 句柄信息,還需要 PROCESS_DUP_HANDLE 權限。如果需要轉儲線程信息,需要 THREAD_ALL_ACCESS 權限。

  • ProcessId:要轉儲的進程ID。

    有點不太理解為什么要額外傳遞一個進程 ID 的參數,調用GetProcessId() 就可以根據 hProcess 獲取進程 ID 了,難道是為了效率?希望有知道的小伙伴兒指點一二。

  • hFile:通過 CreateFile() 等 API 打開的,用來保存 dump 的文件句柄。

  • DumpType:轉儲類型。此參數會直接影響轉儲文件的大小,如果想自己寫一個手動收集 dump 的工具,了解下這個參數會很有用。稍后介紹。

  • ExceptionParam:指向異常信息結構 MINIDUMP_EXCEPTION_INFORMATION 的指針。如果本參數為 NULL,則轉儲文件中不會包含異常信息。

typedefstruct _MINIDUMP_EXCEPTION_INFORMATION {DWORD ThreadId;PEXCEPTION_POINTERS ExceptionPointers;BOOL ClientPointers;} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
  • UserStreamParam:指向用戶自定義信息結構 MINIDUMP_USER_STREAM_INFORMATION 的指針。如果本參數為 NULL,則轉儲文件中不會包含用戶定義的信息。

typedefstruct _MINIDUMP_USER_STREAM_INFORMATION {ULONG UserStreamCount;PMINIDUMP_USER_STREAM UserStreamArray;} MINIDUMP_USER_STREAM_INFORMATION, *PMINIDUMP_USER_STREAM_INFORMATION;
  • CallbackParam:指向回調例程 MINIDUMP_CALLBACK_INFORMATION 的指針。如果此參數為NULL,轉儲過程中不會執行任何回調例程。

typedefstruct _MINIDUMP_CALLBACK_INFORMATION {MINIDUMP_CALLBACK_ROUTINE CallbackRoutine;PVOID CallbackParam;} MINIDUMP_CALLBACK_INFORMATION, *PMINIDUMP_CALLBACK_INFORMATION;

本結構中的CallbackParam 是傳遞給回調函數的參數,用戶可以指定一些自己需要傳遞的參數,很常見的做法。CallbackRoutine 是回調函數,類型為 MINIDUMP_CALLBACK_ROUTINE 。原型如下:

typedefBOOL(WINAPI * MINIDUMP_CALLBACK_ROUTINE) (_Inout_ PVOID CallbackParam,_In_ PMINIDUMP_CALLBACK_INPUT CallbackInput,_Inout_ PMINIDUMP_CALLBACK_OUTPUT CallbackOutput);

因為 DumpType會影響最后生成的轉儲文件的大小,這里介紹下這個參數。

DumpType 參數

DumpType 類型為 MINIDUMP_TYPE。以下定義摘自 10.0.18362.0 版本的 minidumpapiset.h,應該是比較全的了。如果你問我:你怎么知道 MINIDUMP_TYPE 定義在這個文件里?答案很簡單:用 File Locator 搜的唄。

搜索結果typedefenum _MINIDUMP_TYPE {MiniDumpNormal = 0x00000000,MiniDumpWithDataSegs = 0x00000001,MiniDumpWithFullMemory = 0x00000002,MiniDumpWithHandleData = 0x00000004,MiniDumpFilterMemory = 0x00000008,MiniDumpScanMemory = 0x00000010,MiniDumpWithUnloadedModules = 0x00000020,MiniDumpWithIndirectlyReferencedMemory = 0x00000040,MiniDumpFilterModulePaths = 0x00000080,MiniDumpWithProcessThreadData = 0x00000100,MiniDumpWithPrivateReadWriteMemory = 0x00000200,MiniDumpWithoutOptionalData = 0x00000400,MiniDumpWithFullMemoryInfo = 0x00000800,MiniDumpWithThreadInfo = 0x00001000,MiniDumpWithCodeSegs = 0x00002000,MiniDumpWithoutAuxiliaryState = 0x00004000,MiniDumpWithFullAuxiliaryState = 0x00008000,MiniDumpWithPrivateWriteCopyMemory = 0x00010000,MiniDumpIgnoreInaccessibleMemory = 0x00020000,MiniDumpWithTokenInformation = 0x00040000,MiniDumpWithModuleHeaders = 0x00080000,MiniDumpFilterTriage = 0x00100000,MiniDumpWithAvxXStateContext = 0x00200000,MiniDumpWithIptTrace = 0x00400000,MiniDumpScanInaccessiblePartialPages = 0x00800000,MiniDumpValidTypeFlags = 0x00ffffff, } MINIDUMP_TYPE;

下面是每個選項的意義,主要翻譯自官方幫助文檔。

名稱描述
MiniDumpNormal只包含調用棧相關信息
MiniDumpWithDataSegs包含已加載的模塊的數據段信息,比如全局變量
MiniDumpWithFullMemory包含全部可訪問的內存
MiniDumpWithHandleData包含句柄信息
MiniDumpFilterMemory過濾一些敏感信息,保護重建調用棧需要的信息
MiniDumpScanMemory掃描,以包含引用內存
MiniDumpWithUnloadedModules包含最近被卸載的模塊信息
MiniDumpWithIndirectlyReferencedMemory包含未直接引用的內存
MiniDumpFilterModulePaths過濾某塊的路徑信息
MiniDumpWithProcessThreadData包含完整的進程和線程信息
MiniDumpWithPrivateReadWriteMemory包含頁面屬性為 PAGE_READWRITE 的頁面
MiniDumpWithoutOptionalData不包含可選數據
MiniDumpWithFullMemoryInfo包含內存區信息
MiniDumpWithThreadInfo包含線程狀態信息
MiniDumpWithCodeSegs包含所有代碼和有關的內存段
MiniDumpWithoutAuxiliaryState關閉輔助內存收集
MiniDumpWithFullAuxiliaryState使用所有的內存收集器
MiniDumpWithPrivateWriteCopyMemory包含頁面屬性為 PAGE_WRITECOPY 的頁面
MiniDumpIgnoreInaccessibleMemory忽略不可訪問的頁面
MiniDumpWithTokenInformation包含安全令牌相關信息。可以在調試的時候使用 "!token" 命令
MiniDumpWithModuleHeaders包含模塊頭相關信息
MiniDumpFilterTriage添加與篩選器分類相關的數據
MiniDumpWithAvxXStateContext
MiniDumpWithIptTrace
MiniDumpValidTypeFlags設置所有標志位

說明:

MINIDUMP_TYPE 的值是不斷發展變化的(向后兼容),舊版本的 DbgHelp.dll 可能不支持某些值,具體可以參考 微軟官方介紹 MINIDUMP_TYPE 的文檔[1]

關于MINIDUMP_TYPE 每一項的作用更為詳細的介紹請參考 Effective minidumps (Part 1)[2] 和 Effective minidumps (Part 2)[3]。真的是超級詳細,強烈建議大家點開看一看!唯一的遺憾是作者寫的比較早,很多新出現的標志沒總結進來,但仍然是非常好的參考資料!

MiniDumpWriteDump() 可以用來生成轉儲文件,我們應該怎么使用呢?

使用場景

通常,我們希望在自己的程序發生異常的時候,能自動保存一份轉儲文件,供我們事后分析。我們需要做的大概是:捕獲各種異常,在異常處理函數中判斷發生的異常是否能恢復,如果不能恢復就保存轉儲文件和其它一些關鍵文件(比如,程序的配置文件,出現問題時的屏幕截圖等),并一起打包并保存,然后提示用戶,讓用戶上傳我們打包好的文件供我們分析。當程序發生異常的時候,我們很難確定發生異常的進程的運行狀態。所以我們需要啟動一個新的進程,并在新進程中調用 MiniDumpWriteDump() 來保存異常進程的信息。

以上的操作看起來比較簡單,但是處理起來,有很多細節需要考慮。比如,我們需要捕獲哪些異常?怎么捕獲這些異常?保存好的文件怎么上傳?通過什么形式上傳?等等等等…… 如果有可以直接拿來使用的框架,就太好了!別說,還真有!

相關開源庫

以上的這些功能,早已經有開源軟件可以用了。作為一個謙卑的程序員,盡量復用現有的輪子吧。給大家推薦一些不錯的開源庫。

  • CrashRpt[4] (之前在項目里用過,如果你想自己手動實現一個類似的,可以參考此項目的代碼)。

  • CrashRpt 官方介紹
  • 除了 CrashRpt,chromium 里使用的 crashpad[5] 也是一個非常好的選擇。google 出品,質量有保障。

    crashpad 的前身是 breakpad[6](根據 google 官方介紹,breakpad 使用的是進程內報告機制,不再建議大家使用)。

  • 適用于.NET程序的 CrashReporter[7]

  • 其它平臺(Android,iOS等)也有類似的開源庫。可以在 github 上搜索 crash report。我就不截圖了。

  • 說明:

    本文介紹的方法只適用于我們自己的程序。如果我們想轉儲其它進程,我們需要借助現有工具(當然,如果有時間和精力,也可以自己寫一個)。關于抓取轉儲的工具的介紹,可以參考之前的文章—— 你需要知道的 N 種抓取 dump 的工具。

    總結

    • 我們可以通過 MiniDumpWriteDump() 來保存轉儲文件。

    • 我們可以借助 CrashRpt, CrashPad 等開源框架來為我們的程序添加崩潰轉儲功能。

    參考資料

    • 《軟件調試》

    • MiniDumpWriteDump 文檔[8]

    • Effective minidumps (Part 1)[2]

    • Effective minidumps (Part 2)[3]

    References:

    [1]

    微軟官方介紹 MINIDUMP_TYPE 的文檔: https://docs.microsoft.com/zh-cn/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_type

    [2]

    Effective minidumps (Part 1): http://www.debuginfo.com/articles/effminidumps.html

    [3]

    Effective minidumps (Part 2): http://www.debuginfo.com/articles/effminidumps2.html

    [4]

    CrashRpt: http://crashrpt.sourceforge.net/

    [5]

    crashpad: https://github.com/chromium/crashpad

    [6]

    breakpad: https://github.com/google/breakpad

    [7]

    CrashReporter: https://github.com/ravibpatel/CrashReporter.NET

    [8]

    MiniDumpWriteDump 文檔: https://docs.microsoft.com/zh-cn/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump


    猜你喜歡:

    轉儲文件系列:

    轉儲文件知多少

    你需要知道的 N 種抓取 dump 的工具

    你生成的轉儲文件有問題嗎?

    JIT Debug Info 簡介

    調試系列:

    調試實戰——你知道怎么使用DebugView查看調試信息嗎?

    調試實戰——程序CPU占用率飆升,你知道如何快速定位嗎?

    調試實戰——崩潰在ComFriendlyWaitMtaThreadProc

    調試實戰——使用windbg調試崩潰在ole32!CStdMarshal::DisconnectSrvIPIDs

    調試實戰——調試PInvoke導致的內存破壞

    調試實戰——調試excel啟動時死鎖

    調試實戰——調試DLL卸載時的死鎖

    調試實戰——調試TerminateThread導致的死鎖

    排錯系列:

    排錯實戰——VS清空最近打開的工程記錄

    排錯實戰——拯救加載調試符號失敗的IDA

    排錯實戰——你知道拖動窗口時只顯示虛框怎么設置嗎?

    排錯實戰——解決Tekla通過.tsep安裝插件失敗的問題

    排錯實戰——使用process explorer替換任務管理器

    排錯實戰——通過對比分析sysinternals事件修復程序功能異常

    歡迎留言交流

    總結

    以上是生活随笔為你收集整理的向大厂看齐!为自己的程序增加自动转储的功能!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。