Windows上使用dump文件調試

dump文件

dump文件記錄當前程序運行某一時刻的信息,包括內存,線程,線程棧,變量等等,相當于調試程序時運行到某個斷點上,把程序運行的信息記錄下來。可以通過Windbg打開dump,查看程序運行的變量等,來調試程序。

在Liunx上也有類似的技術,Coredump,具體可以參考:coredump詳解_coredump文件分析_賀二公子的博客-CSDN博客

dump 文件分類

dump可以分為 minidump 和 Full dump

minidump通常只包含了一些關鍵信息,一般比較小,通常只要幾MB,

Full dump包含了程序運行時的所有信息,包括程序的所有內存,一般有幾十MB到幾GB。

minidump雖然只包含了部分信息,但這些信息大部分情況足夠用于調試,所以大部分情況都是使用minidump調試

生成dump文件

通過任務管理器導出

在進程上右擊->創建內存轉儲文件,這樣創建的是Full dump

通過Process Explorer導出

Process Explorer - Sysinternals | Microsoft Learn

選擇對應的進程->Process->Create Dump,然后選擇要創建minidum 還是 Full Dump

使用MiniDumpWriteDump函數序生成?

#include <iostream>
#include <Windows.h>
#include <Dbghelp.h>
#include <thread>
#pragma comment(lib, "Dbghelp.lib")void createMinidump()
{wchar_t DumpPath[MAX_PATH] = {0};SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[256] = {0};GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth,SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);if (file != INVALID_HANDLE_VALUE){DWORD Flags = MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpScanMemory|MiniDumpWithIndirectlyReferencedMemory |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD) GetCurrentProcessId(), file,(MINIDUMP_TYPE) (Flags),nullptr, nullptr, nullptr) != 0){std::cout << "Create Minidump successful!! file:";std::wcout << DumpPath << std::endl;}else{std::cout << "Create Minidump failed!!" << std::endl;}}CloseHandle(file);
}void createFullDump()
{wchar_t DumpPath[MAX_PATH] = {0};SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[256] = {0};GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d_full.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth,SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);if (file != INVALID_HANDLE_VALUE){const DWORD Flags = MiniDumpWithFullMemory |MiniDumpWithFullMemoryInfo |MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD) GetCurrentProcessId(), file,(MINIDUMP_TYPE) (Flags),nullptr, nullptr, nullptr) != 0){std::cout << "Create Full dump successful!! file:";std::wcout << DumpPath << std::endl;}else{std::cout << "Create Full dump failed!!" << std::endl;}}CloseHandle(file);
}

程序崩潰時自動導出Dump

我們希望程序運行崩潰時可以自動導出dump,這樣可以通過分析dump文件找到崩潰原因。

程序崩潰很多情況都是由異常引起的,Windows提供了SetUnhandledExceptionFilter函數用來設置一個函數指針,用于處理未處理的異常,可以在這個函數中導出Dump文件。

1. 準備一個處理異常的函數,并在其中導出dump。異常處理函數有一個參數,這個參數記錄了當前異常信息,這個異常信息可以一起隨dump文件導出,方便后續查找文件

LONG WINAPI DumpException(EXCEPTION_POINTERS* info)
{std::cout << "DumpException, Thread ID:"<< std::this_thread::get_id() << std::endl;std::cout << "Exception: 0x" << std::hex << info->ExceptionRecord->ExceptionCode << std::endl;wchar_t DumpPath[MAX_PATH] = { 0 };SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[100] = { 0 };GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d_crash.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);if (file != INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION mdei;mdei.ThreadId = (DWORD)GetCurrentThreadId();mdei.ExceptionPointers = info;mdei.ClientPointers = 0;DWORD Flags = MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpScanMemory|MiniDumpWithIndirectlyReferencedMemory |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;//        Flags = MiniDumpWithFullMemory |
//                MiniDumpWithFullMemoryInfo |
//                MiniDumpWithHandleData |
//                MiniDumpWithUnloadedModules |
//                MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD)GetCurrentProcessId(), file,(MINIDUMP_TYPE)(Flags),&mdei, nullptr, nullptr) != 0){std::cout << "Create Crash dump successful!! file:";std::wcout << DumpPath << std::endl;CloseHandle(file);return EXCEPTION_EXECUTE_HANDLER;}}std::cout << "Create Crash dump failed!!" << std::endl;CloseHandle(file);return EXCEPTION_CONTINUE_SEARCH;
}

2. 在程序啟動時設置異常處理函數

int main()
{std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;LPTOP_LEVEL_EXCEPTION_FILTER oldExceptionFilter = nullptr;oldExceptionFilter = SetUnhandledExceptionFilter(&DumpException);// ... ...// ... ...}

PS

1. 這里是通過異常捕獲生成dump,如果是調用abort,exit,TerminateProcess, TerminateThread函數,這些函數會立即結束函數,所以不會生成dump。

2.?SetUnhandledExceptionFilter是全局的,只需設置一次,設置后對所有線程有效。SetUnhandledExceptionFilter有些異常捕獲不到。

3. 可以使用第三方庫捕獲崩潰事件,例如:crashrpt,google breakpad,qBreakpad,Crashpad

UnhandledExceptionFilter未處理的異常

Windows中所有的函數都是從BaseThreadStart函數開始運行

VOID BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) {
__try {
ExitThread((pfnStartAddr)(pvParam));
}
__except (UnhandledExceptionFilter(GetExceptionInformation())) {
ExitProcess(GetExceptionCode());
}
// NOTE: We never get here
}

這里的函數UnhandledExceptionFilter用來處理線程中捕獲的未處理的異常,調用SetUnhandledExceptionFilter就是用來設置這個函數。

這里的__try{}__except{} 是?Windows系統的結構化異常處理(SEH),具體參考 《Windows核心編程第五版》——第24章

使用VS調試Dump文件

調試Dump文件,dump文件以外,還需要pdb符號文件,pdb符號文件是編譯時和exe程序同時生成的,默認情況下Debug版本會生成符號文件,Release文件不生成符號文件,Release模式下需要收到打開生成符號文件。

打開Dump文件

文件->打開->文件,選擇dump文件

設置符號文件

符號文件(pdb)必須保證時和exe同時生成的,且不能改文件名,否則會加載失敗

有兩種方法

1. 把符號文件和dump文件放在同一個目錄下,VS在加載dump時會讀取dump目錄下的符號文件。

2. 通過 【工具->選項->調試->符號】設置符號文件路徑。

?3. 點擊右上角的 【使用 混合 進行調試】,則可以查看dump文件的內容,和調試模式下運行出現異常是一樣的。

?

使用Windbg調試Dump文件

Windbg 下載?Install WinDbg - Windows drivers | Microsoft Learn

Windbg打開dump后會提示是否有異常

調試步驟:

1. 設置符號文件 【文件->settings->debuging settings】

2. 輸入 .ecxr 命令

3. 輸入 kn 命令

查看exe編譯時間

lm vm test_win*

通過這個時間可以去查找exe對應的pdb文件?

完整代碼例子:小康6650/StudyProject - Gitee.com

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41345.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41345.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41345.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql 修改存儲路徑,重啟失敗授權

目錄 停掉mysql修改mysql 配置文件my.cnf目錄授權重啟mysql 停掉mysql 修改mysql 配置文件my.cnf 更改mysql 存儲位置 到/data/mysql_data目錄下&#xff1a; datadir/data/mysql/mysql_data/socket/data/mysql/mysql_data/mysql.sockmysql 默認路么徑在 /var/lib/mysql/ 防止…

go_并發編程(1)

go并發編程 一、 并發介紹1&#xff0c;進程和線程2&#xff0c;并發和并行3&#xff0c;協程和線程4&#xff0c;goroutine 二、 Goroutine1&#xff0c;使用goroutine1&#xff09;啟動單個goroutine2&#xff09;啟動多個goroutine 2&#xff0c;goroutine與線程3&#xff0…

在 React 中獲取數據的6種方法

一、前言 數據獲取是任何 react 應用程序的核心方面。對于 React 開發人員來說&#xff0c;了解不同的數據獲取方法以及哪些用例最適合他們很重要。 但首先&#xff0c;讓我們了解 JavaScript Promises。 簡而言之&#xff0c;promise 是一個 JavaScript 對象&#xff0c;它將…

Python Web:Django、Flask和FastAPI框架對比

原文&#xff1a;百度安全驗證 Django、Flask和FastAPI是Python Web框架中的三個主要代表。這些框架都有著各自的優點和缺點&#xff0c;適合不同類型和規模的應用程序。 1. Django&#xff1a; Django是一個全功能的Web框架&#xff0c;它提供了很多內置的應用程序和工具&am…

排序+運算>直接運算的效率的原因分析

大家好,我是愛編程的喵喵。雙985碩士畢業,現擔任全棧工程師一職,熱衷于將數據思維應用到工作與生活中。從事機器學習以及相關的前后端開發工作。曾在阿里云、科大訊飛、CCF等比賽獲得多次Top名次。現為CSDN博客專家、人工智能領域優質創作者。喜歡通過博客創作的方式對所學的…

ADIS16470和ADIS16500從到手到讀出完整數據,附例程

由于保密原因&#xff0c;不能上傳我這邊的代碼&#xff0c;我所用的開發環境是IAR&#xff0c; 下邊轉載別的博主的文章&#xff0c;他用的是MDK 下文的博主給了你一個很好的思路&#xff0c;特此提出表揚 最下方是我做的一些手冊批注&#xff0c;方便大家了解這個東西 原文鏈…

如何利用 ChatGPT 進行自動數據清理和預處理

推薦&#xff1a;使用 NSDT場景編輯器助你快速搭建可二次編輯的3D應用場景 ChatGPT 已經成為一把可用于多種應用的瑞士軍刀&#xff0c;并且有大量的空間將 ChatGPT 集成到數據科學工作流程中。 如果您曾經在真實數據集上訓練過機器學習模型&#xff0c;您就會知道數據清理和預…

有沒有比讀寫鎖更快的鎖

在之前的文章中&#xff0c;我們介紹了讀寫鎖&#xff0c;學習完之后你應該已經知道了讀寫鎖允許多個線程同時訪問共享變量&#xff0c;適用于讀多寫少的場景。那么在讀多寫少的場景中還有沒有更快的技術方案呢&#xff1f;還真有&#xff0c;在Java1.8這個版本里提供了一種叫S…

Docker安裝Skywalking APM分布式追蹤系統

Skywalking是一個應用性能管理(APM)系統&#xff0c;具有服務器性能監測&#xff0c;應用程序間調用關系及性能監測等功能&#xff0c;Skywalking分為服務端、管理界面、以及嵌入到程序中的探針部分&#xff0c;由程序中的探針采集各類調用數據發送給服務端保存&#xff0c;在管…

novnc 和 vnc server 如何實現通信?原理?

參考&#xff1a;https://www.codenong.com/js0f3b351a156c/

隨機微分方程

應用隨機過程|第7章 隨機微分方程 見知乎&#xff1a;https://zhuanlan.zhihu.com/p/348366892?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

復習3-5天【80天學習完《深入理解計算機系統》】第七天

專注 效率 記憶 預習 筆記 復習 做題 歡迎觀看我的博客&#xff0c;如有問題交流&#xff0c;歡迎評論區留言&#xff0c;一定盡快回復&#xff01;&#xff08;大家可以去看我的專欄&#xff0c;是所有文章的目錄&#xff09;   文章字體風格&#xff1a; 紅色文字表示&#…

Linux與bash(基礎內容一)

一、常見的linux命令&#xff1a; 1、文件&#xff1a; &#xff08;1&#xff09;常見的文件命令&#xff1a; &#xff08;2&#xff09;文件屬性&#xff1a; &#xff08;3&#xff09;修改文件屬性&#xff1a; 查看文件的屬性&#xff1a; ls -l 查看文件的屬性 ls …

神經網絡基礎-神經網絡補充概念-33-偏差與方差

概念 偏差&#xff08;Bias&#xff09;&#xff1a; 偏差是模型預測值與實際值之間的差距&#xff0c;它反映了模型對訓練數據的擬合能力。高偏差意味著模型無法很好地擬合訓練數據&#xff0c;通常會導致欠擬合。欠擬合是指模型過于簡單&#xff0c;不能捕捉數據中的復雜模式…

基于java在線讀書與分享論壇設計與實現

摘 要 互聯系統的技術在如今的社會中&#xff0c;應用的越來越廣泛&#xff0c;通過互聯系統我們可以更方便地進行辦公&#xff0c;也能夠在系統上就能處理很多日常的事務。互聯系統的技術的發展&#xff0c;也是人們日常中接觸更多的一項技術。隨著互聯系統的發展&#xff0c;…

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 摘要當前的檢測sota模型網絡架構swin Transformer和Vision Transformer的不同之處整體架構Patch Partition結構Linear Embedding結構Swin Transformer Block結構 Patch MergingW-MSAMSA模塊計算量W-M…

學習Vue:Vue3 VS Vue2

Vue 3作為Vue.js的最新版本&#xff0c;帶來了一系列令人激動的新特性和改進&#xff0c;讓開發者們在構建現代Web應用時體驗更加順暢和高效。本文將全面介紹Vue 3相對于Vue 2的改進&#xff0c;重點解釋Composition API的使用&#xff0c;以及新引入的Teleport和Suspense等特性…

Genoss GPT簡介:使用 Genoss 模型網關實現多個LLM模型的快速切換與集成

一、前言 生成式人工智能領域的發展繼續加速&#xff0c;大型語言模型 (LLM) 的用途范圍不斷擴大。這些用途跨越不同的領域&#xff0c;包括個人助理、文檔檢索以及圖像和文本生成。ChatGPT 等突破性應用程序為公司進入該領域并開始使用這項技術進行構建鋪平了道路。 大公司正…

如何發布自己的小程序

小程序的基礎內容組件 text&#xff1a; 文本支持長按選中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染為對應的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

MySql過濾重復數據

假設模型表是: 1. 根據單字段過濾: SELECT user_name, COUNT(*) as count FROM sys_user GROUP BY user_name HAVING count > 1;結果: 2. 根據多個字段查詢重復數據 SELECT user_name, email, COUNT(*) as count FROM sys_user GROUP BY user_name, email HAVING count…