[轉]window下使用SetUnhandledExceptionFilter捕獲讓程序的崩潰

簡單使用SetUnhandledExceptionFilter()函數讓程序優雅崩潰html

雖然是大公司的產品,QQ它仍是會在咱們的折騰下崩潰的,可是它老是崩潰的很優雅,還要彈出本身的對話框來結束。而且發送報告,去掉了系統默認的發送報告的對話框。程序員

因此一拍腦殼,想讓本身的程序崩潰的體面一點。數據庫

本身想了大概的思路,以爲能夠用一個進程來監控目標程序。的確也能夠拿到了目標程序崩潰的信息,知道它何時崩潰的,也能夠作額外的操做,可是這樣是沒辦法把默認的發送錯誤的對話框去掉的。windows

而後又有人說是否是採用了相似鉤子的方法把這個東西在哪裏勾掉了。服務器

最後網上查了一番,發現SetUnhandledExceptionFilter這個函數解決了一切。網絡

總結了下搜到的資料,這個函數的返回值有三種狀況:app

 

EXCEPTION_EXECUTE_HANDLER equ 1 表示我已經處理了異常,能夠優雅地結束了  
EXCEPTION_CONTINUE_SEARCH equ 0 表示我不處理,其餘人來吧,因而windows調用默認的處理程序顯示一個錯誤框,並結束  
EXCEPTION_CONTINUE_EXECUTION equ -1 表示錯誤已經被修復,請從異常發生處繼續執行 ide

 

具體使用方法以下:函數

 

  #include   <windows.h>   
    
  long   __stdcall   callback(_EXCEPTION_POINTERS*   excp)   
  {   
  MessageBox(0,"Error","error",MB_OK);   
  printf("Error   address   %x/n",excp->ExceptionRecord->ExceptionAddress);   
  printf("CPU   register:/n");   
  printf("eax   %x   ebx   %x   ecx   %x   edx   %x/n",excp->ContextRecord->Eax,   
  excp->ContextRecord->Ebx,excp->ContextRecord->Ecx,   
  excp->ContextRecord->Edx);   
  return   EXCEPTION_EXECUTE_HANDLER;   
  }
    
  int   main(int   argc,char*   argv[])   
  {   
  SetUnhandledExceptionFilter(callback);   
  _asm   int   3   //只是爲了讓程序崩潰
  return   0;   
  }工具

 

vs 調試dump

貌似只有vs 05以上的版本,能調試dump文件。

1. dump文件和pdb文件的匹配問題

>> 發佈二進制文件時生成的pdb文件必定要保留,只有當發佈的二進制文件和pdb文件是同時生成的纔好正確調試。

2. dump文件和pdb文件放在哪裏的問題

>> 若是dump文件和pdb文件放在同一個目錄,則可直接運行調試;固然也能夠不是同一個目錄,那麼在啓動dmp文件後,須要設置一下vs的符號文件路徑:Tools->Options->Debugging->Symbols. 若是須要調試windows自帶的一些dll或者exe,則能夠在這裏添加windows的pdb文件服務器:http://msdl.microsoft.com/download/symbols

3. 二進制文件放在哪裏的問題

>> 現場恢復須要二進制文件,但沒必要全部的二進制文件都須要,因此即便你的機器和用戶的機器操做系統不同也不要緊;出問題的若是是你發佈的二進制文件,則只須要你發佈的二進制文件就能夠了。vs在加載二進制的文件失敗的時候會打印出其詳細路徑,但這是用戶機器上的路徑,沒有必要必定要跟這個路徑同樣,把你發佈的二進制文件放到dump文件目錄就能夠了。

4. 顯示不了源代碼的問題

>> 首先須要設置源代碼目錄,右鍵solution:Properties->Common Properties->Debug Source Files,裏邊加入你的本地源代碼目錄就是了;可是若是代碼已經改過了,恢復不到當時的狀態,vs顯示不了源碼怎麼辦?只要設置:Tools->Options->Debugging->General->Require source files to exactly match the original version 這個複選框鉤掉就能夠了

 

Minidump方式保留程序崩潰現場

在Windows平臺下用C++開發應用程序,最不想見到的狀況恐怕就是程序崩潰,而要想解決引發問題的bug,最困難的應該就是調試release版本了。由於release版原本就少了不少調試信息,更況且通常都是發佈出去由用戶使用,crash的現場很難保留和重現。目前有一些方法能夠解決:崩潰地址 + MAP文件;MAP文件;SetUnhandledExceptionFilter + Minidump。本文重點解決Minidump方式。

1、Minidump文件生成

  一、Minidump概念

    minidump(小存儲器轉儲)能夠理解爲一個dump文件,裏面記錄了可以幫助調試crash的最小有用信息。實際上,若是你在系統屬性 -> 高級 -> 啓動和故障恢復 -> 設置 -> 寫入調試信息中選擇「小內存轉儲(64 KB)」的話,當系統意外中止時都會在C:\Windows\Minidump\路徑下生成一個.dmp後綴的文件,這個文件就是minidump文件,只不過這個是內核態的minidump。

   咱們要生成的是用戶態的minidump,文件中包含了程序運行的模塊信息、線程信息、堆棧調用信息等。並且爲了符合其mini的特性,dump文件是壓縮過的。

二、生成minidump文件

經過drwtsn3二、NTSD、CDB等調試工具生成Dump文件, drwtsn32存在的缺點雖然NTSD、CDB能夠徹底解決,但並非全部的操做系統中都安裝了NTSD、CDB等調試工具。根據MiniDumpWriteDump接口,徹底能夠程序自動生成Dump文件。

 

三、  自動生成Minidump文件

當程序遇到未處理異常(主要指非指針形成)致使程序崩潰死,若是在異常發生以前調用了SetUnhandledExceptionFilter()函數,異常交給函數處理。MSDN中描述爲:

Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.

 於是,在程序開始處增長SetUnhandledExceptionFilter()函數,並在函數中利用適當的方法生成Dump文件,便可實現須要的功能。

生成dump文件類(minidump.h)#pragma once  

  
   
  
#include <windows.h>  
  
#include <imagehlp.h>  
  
#include <stdlib.h>  
  
#pragma comment(lib, "dbghelp.lib")  
  
  
inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName)  
{  
    if(pModuleName == 0)  
  
    {  
  
       return FALSE;  
  
    }  
  
    WCHAR szFileName[_MAX_FNAME] = L"";  
  
    _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);  
  
    if(wcsicmp(szFileName, L"ntdll") == 0)  
       return TRUE;  
  
    return FALSE;   
}  
  
   
  
inline BOOL CALLBACK MiniDumpCallback(PVOID         pParam,   
                                  const PMINIDUMP_CALLBACK_INPUT   pInput,   
                                  PMINIDUMP_CALLBACK_OUTPUT        pOutput)  
  
{  
    if(pInput == 0 || pOutput == 0)  
       return FALSE;  

    switch(pInput->CallbackType)  
    {  
    case ModuleCallback: 
    {    if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg)    if(!IsDataSectionNeeded(pInput->Module.FullPath))    pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
       }
    break; case IncludeModuleCallback: case IncludeThreadCallback: case ThreadCallback: case ThreadExCallback: return TRUE; default:
      break; } return FALSE; } //建立Dump文件 inline void CreateMiniDump(EXCEPTION_POINTERS* pep, LPCTSTR strFileName) { HANDLE hFile = CreateFile(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) { MINIDUMP_EXCEPTION_INFORMATION mdei; mdei.ThreadId = GetCurrentThreadId(); mdei.ExceptionPointers = pep; mdei.ClientPointers = FALSE; MINIDUMP_CALLBACK_INFORMATION mci; mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback; mci.CallbackParam = 0; MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)0x0000ffff; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, NULL, &mci); CloseHandle(hFile); } } LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { return NULL; } BOOL PreventSetUnhandledExceptionFilter() { HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); if (hKernel32 == NULL) return FALSE; void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); if(pOrgEntry == NULL) return FALSE; unsigned char newJump[ 100 ]; DWORD dwOrgEntryAddr = (DWORD) pOrgEntry; dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far void *pNewFunc = &MyDummySetUnhandledExceptionFilter; DWORD dwNewEntryAddr = (DWORD) pNewFunc; DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; newJump[ 0 ] = 0xE9; // JMP absolute memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); SIZE_T bytesWritten; BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); return bRet; } LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException) { TCHAR szMbsFile[MAX_PATH] = { 0 }; ::GetModuleFileName(NULL, szMbsFile, MAX_PATH); TCHAR* pFind = _tcsrchr(szMbsFile, '\\'); if(pFind) { *(pFind+1) = 0; _tcscat(szMbsFile, _T("CreateMiniDump.dmp")); CreateMiniDump(pException,szMbsFile); } // TODO: MiniDumpWriteDump FatalAppExit(-1, _T("Fatal Error")); return EXCEPTION_CONTINUE_SEARCH; } //運行異常處理 void RunCrashHandler() { SetUnhandledExceptionFilter(UnhandledExceptionFilterEx); PreventSetUnhandledExceptionFilter(); }

  


 

//測試實現文件

// 一個有函數調用的類

 

class CrashTest

{
public:
    void Test()
    {
       Crash();
    }
private:
    void Crash()
    {
         strcpy(NULL,"adfadfg");
    }
};

int _tmain(int argc, _TCHAR* argv[])

{
    //設置異常處理函數
    RunCrashHandler();

    CrashTest test;

    test.Test();

    getchar();

    return 0;
}

 

  

注意事項

一、須要配置debug選項,在C/C++選項à常規à調試信息格式(設置爲程序數據庫(/Zi));在鏈接器選項—>調試à生成調試信息(設置爲是);C/C++選項à優化à禁用。(參見下圖)

二、  可執行文件(exe)必須找到dbghelp.dll,才能生成Dump文件。這個DLL能夠從調試工具包中找到。

三、*.exe、*.pdb、*.dump、dbghelp.dll 這四個文件須要放在同一目錄下才好調試,雙擊dump文件時,就能夠自動關聯到出錯代碼位置。

四、爲了獲取更多更深刻的調試信息,須要把程序優化開關設置成禁用。

五、 當異常代碼定位成功之後,若是沒法阻止異常的產生,能夠用 __try 結構包裝異常代碼,__try 和 try 不一樣,前者能夠捕獲非法指針產生的異常。

__try {

// 會異常的函數

}

__except( EXCEPTION_EXECUTE_HANDLER ){

// 異常處理

}

2、調試Minidump文件

  1. 雙擊minidump文件(*.dmp)。默認會啓動vs2008。
  2. 菜單Tools/Options, Debugging/Symbols,增長PDB文件路徑。注:若是minidump文件與pdb文件在同一目錄,就不用設置這個了。
  3. 若調試的程序須要微軟基礎庫的PDB信息,能夠增長一個路徑爲:
  4. http://msdl.microsoft.com/download/symbols
  5. 在界面下方Cache Symbol From symbol…選擇本地存儲這些Symbols的路徑。 注:若是本地已存儲過微軟基礎庫的pdb,就直接按照此步操做設置本地路徑,沒必要執行上一步操做了。
  6. 設置代碼路徑:
 

設置代碼路徑:

剛打開的dmp工程,進入解決方案的屬性。在這裏輸入源程序的代碼路徑。注:必定是sln所在的路徑,而不是vcproj的路徑!

 

 

按F5,debug吧。

demo代碼下載:http://download.csdn.net/detail/byxdaz/7349325

 

 

 

 

 







 

調試方法不用上述那麼麻煩,直接在Debug目錄下 或者 Release目錄下 exe + pdb + dmp 在同一目錄,而後雙擊dmp文件VC2010就能夠打開,而後點擊右上角的調試按鈕就能夠直接定位到崩潰的代碼了;

參考這裏: http://blog.csdn.net/starlee/article/details/6630816

 

 

別人機器上的dump調試:

http://blog.csdn.net/xhk456/article/details/7523150

 

 

這段時間忽然發現,要一下作一個金剛不壞之身的程序是不太可能滴,至於對我來講吧。
這個程序也要通過千錘百煉纔可以練就一個強大的自信心。

 

我如今作系統就不考慮一下把程序作的足夠強壯了,由於我也作不到大哭,如今作系統時,總考慮的一個問題:

當系統異常的時候怎麼去處理?

 

我不怕系統程序出現異常,甚至直接Over,只要能在異常時處理異常後繼續運做,在崩潰重啓後可以繼續把沒

乾的活給幹了,那麼這個在我可以承受的範圍內,也在大多數客戶的承受範圍內,由於這樣就是咱們所說的將

損失減少到最低,實際上是不是最低只有本身可以知道。

 

固然了,我更但願可以作出一個健壯無比的牛逼程序,因此我想知道程序是在什麼狀況下崩潰的,但是有些問題

你懂的,老在客戶機器上或者生產環境下出現,卻在本身的機器上和測試環境就他媽的不出現,碰見這種狀況我是

跳樓或者殺人的心情都有了,偶爾我也犯過情緒,想提出辭職申請,換個行業去,告別這苦逼的程序員生涯,

可總不知道是什麼力量支持着我,讓我堅強依舊滴作着程序員,過着狗日的日子。

 

後來,不經意間,一位同事給我說了一個種在系統中異常或者崩潰的時候,來生成dump文件,而後用調試器來調試。

這樣就能夠在生產環境中的dmp文件,拷貝到本身的開發機器上,調試就能夠找到錯誤的位置,配合程序調試符號pdb文件,

直接能夠定位到源代碼中位置,真是太他媽的神奇了,雖然Release版本下的不少變量的值是不對滴,但並不影響我這個

這麼有執着心的coder來找bug。

 

同事給了我他寫的示例,往空指針拷貝數據,在非調試下運行後,果真的崩了,果斷滴生成了一個擴展名爲dmp的文件,

而後他用vs2010打開那個dmp文件,vs2010很果斷滴定位到了那個往空指針拷貝數據那裏。

看他那嫺熟的操做,頓時感受到了他的強大和微軟的牛逼。

 

後來我就學他,在程序中加入程序異常時產生dump文件的功能,待系統發佈後,在一次不經意間一個程序掛掉了。

在客戶的謾罵中,我面帶笑容說:這個問題很好解決。我滿懷信心滴從服務器上拷貝了程序崩潰產生dump文件,

而後學着那個同事用vs2010打開,我了個去,咋沒有定位到源代碼中內,只定位到了可執行文件的一個地址,這讓哥

情何以堪吶!

 

還好,我對pdb瞭解還比較熟悉,想來應該是符號文件的問題,因而就開始摸索的,不經意見的在

堆棧處右擊了下,發現菜單里居然有「加載符號」,並且還有「符號路徑」,我想這大概就是讓我來選擇

對應的pdb文件吧,頓時感受曙光就在前面。

點擊了「符號路徑」後以下圖:

才發現了,它並非來選擇符號文件,而是選擇對應的可執行程序的路徑,選擇了後果斷滴定位到了源代碼的位置,

才發現一個很簡單很美麗的bug,修改後,在測試後重現發佈,系統的健壯性又提升了一個臺階。

 

回頭想了想,我同事給我演示的時候,他程序運行的目錄和就是他直接用vs2010生成的目錄,因此此種狀況下

用vs2010打開dmp文件便可定位到源代碼文件。而發佈後的程序,通常狀況下你根本不知作別人放在什麼地方去執行的,

所以調試時還並必須選相同版本的可執行文件,而後pdb文件纔會好好工做,要不沒可執行文件,咋個調試嘛。

 

哎,這同事,竟然還留了一手,坑爹啊。

 

不過仍是要感謝他滴,我又掌握了一些東西,又加強了我這個苦逼程序員寫好程序的信心。

 

在寫這個以前看了相關文章,感受比較好的推薦一哈:

http://www.cppblog.com/woaidongmao/archive/2011/05/10/146086.html

 

 

 

到這裏,你就能夠在你的工程中經過代碼的方式添加,在程序崩潰的時候回建立dump文件了;

.dump

 

.dump 命令建立一個用戶模式或內核模式崩潰轉儲文件。分析工具:https://msdn.microsoft.com/en-us/library/windows/desktop/ee416349(v=vs.85).aspx#writing_a_minidump

程序崩潰(crash)的時候, 爲了之後可以調試分析問題, 可使用WinDBG要把當時程序內存空間數據都保存下來,生成的文件稱爲dump 文件。 步驟:

1) 打開WinDBG並將之Attach 到crash的程序進程

2) 輸入產生dump 文件的命令

直接用.dump -?能夠看到它的簡單說明:

[cpp]  view plain copy
 
 
  1. 0:000> .dump -?  
  2. Usage: .dump [options] filename  
  3. Options are:  
  4.   /a - Create dumps for all processes (requires -u)  
  5.   /b[a] - Package dump in a CAB and delete dump  
  6.   /c <comment> - Add a comment (not supported in all formats)  
  7.   /j <addr> - Provide a JIT_DEBUG_INFO address  
  8.   /f - Create a legacy style full dump  
  9.   /m[acdfFhiprRtuw] - Create a minidump (default)  
  10.   /o - Overwrite any existing file  
  11.   /u - Append unique identifier to dump name  

 

/o :覆蓋具備相同名字的dump文件。若是沒有使用該選項又存在一個相同名字的文件,則dump文件不會被寫入:好比個人C盤原有一個myapp.dmp文件:

[cpp]  view plain copy
 
 
  1. 0:000> .dump c:/myapp.dmp  
  2. Unable to create file 'c:/myapp.dmp' - Win32 error 0n80  
  3.     "文件存在。"  
  4. 0:000> .dump /o c:/myapp.dmp  
  5. Creating c:/myapp.dmp - mini user dump  
  6. Dump successfully written  

/f (用戶模式:) 建立一個完整用戶模式dump,這裏要注意不要字面理解,

完整用戶模式dump是基本的用戶模式dump文件。這種dump文件包含進程的完整內存空間、程序自己的可執行映像、句柄表和其餘對調試器有用的信息

注意 和名字無關,最大的"minidump"文件實際上能夠提供比完整用戶模式dump更多的信息。例如,.dump /mf.dump /ma將建立比.dump /f更大更完整的文件。

用戶模式下,使用.dump /m[MiniOptions] 是最好的選擇。經過這個開關建立的dump文件能夠很小也能夠很大。經過指定合適的MiniOptions 能夠控制究竟須要包含哪些信息。

 

[cpp]  view plain copy
 
 
  1. 0:000> .dump /o/f c:/myapp.dmp  
  2. *****************************************************************************  
  3. * .dump /ma is the recommend method of creating a complete memory dump      *  
  4. * of a user mode process.                                                   *  
  5. *****************************************************************************  
  6. Creating c:/myapp.dmp - user full dump  
  7. Dump successfully written  


咱們看到了,系統給出了提示:.dump /ma是建立完整dump的推薦方式(用戶模式下)

/m[MiniOptions] 建立一個小內存dump(內核模式)或者 minidump (用戶模式)。若是沒有指定 /f /m ,/m 是默認選項。用戶模式下,/m 後面能夠跟附加的MiniOptions 用來指定dump文件中包含的數據。若是沒有使用MiniOptions ,dump文件包含模塊、線程和調用堆棧信息,可是沒有其餘附加信息

MiniOption 做用
a 建立一個包含全部附加選項的minidump。/ma選項至關於/mfFhut —它會在minidump中添加完整的內存數據、句柄數據、已卸載模塊信息、基本內存信息和線程時間信息。
f 在minidump中包含完整內存數據。目標程序擁有的全部 可訪問的已交付的頁面(committed pages)都會包含進去。
F 在minidump中添加全部基本內存信息。這會將一個流加入到包含完整基本內存信息的minidump中,而不單是可以使用的內存。這樣可使得調試器可以重建minidump生成時進程的完整虛擬內存佈局。
h 在minidump中包含和目標進程相關的句柄信息。
u 在minidump中包含已卸載模塊信息。僅在Windows Server 2003和以後版本的Windows中可用。
t 在minidump中包含附加的線程信息。包括能夠在調試minidump時使用!runaway擴展命令或.ttime (Display Thread Times)命令進行顯示的線程時間。
i 在minidump中包含次級內存(secondary memory)。次級內存是由堆棧中的指針或備份存儲(backing store)中引用到的任何內存,加上該地址周圍的一小段區域。
p 在minidump中包含進程環境塊(PEB)和線程環境塊(TEB)。這在想訪問程序的進程和線程相關的Windows系統信息時頗有用。
w 將全部已交付的可讀寫的私有頁面包含進minidump。
d 在minidump中包含可執行映像中全部可讀寫的數據段。
c 加入映像中的代碼段。
r 從minidump中去掉對重建調用堆棧無用的堆棧和存儲內存部分。局部變量和其餘數據類型值也被刪除。這個選項不會使得minidump變小(由於這些內存節僅僅是變成0),可是當想保護其餘程序中的機密信息時有用。
R 在minidump中去掉完整的模塊路徑。僅包含模塊名。若是想保護用戶的目錄結構時該選項有用。

選項(1): /m

命令行示例:.dump /m C:/dumps/myapp.dmp

註解: 缺省選項,生成標準的minidump, 轉儲文件一般較小,便於在網絡上經過郵件或其餘方式傳輸。 這種文件的信息量較少,只包含系統信息、加載的模塊(DLL)信息、 進程信息和線程信息。

選項(2): /ma

命令行示例:.dump /ma C:/dumps/myapp.dmp

註解: 帶有儘可能多選項的minidump(包括完整的內存內容、句柄、未加載的模塊,等等),文件很大,但若是條件容許(本機調試,局域網環境), 推薦使用這中dump。

選項(3):/mFhutwd

命令行示例:.dump /mFhutwd C:/dumps/myapp.dmp

註解:帶有數據段、非共享的讀/寫內存頁和其餘有用的信息的minidump。包含了經過minidump可以獲得的最多的信息。是一種折中方案。

Fhutwd按字母對應上面的MiniOptions表示

 

//-xp自動生成dump-----------------------------------------------------------------------------------------------------------------------------------------------------------------

那怎麼自動生成dump文件呢,好比對方的電腦沒有windbg,這裏用到一個window XP系統自帶工具,Dr.Watson

運行方式很簡單:

直接run-輸入drwtsn32 -i就能夠了,會提示這樣的:

這個命令真難記,實話,記華生醫生吧,福爾摩斯中的

若是有程序崩潰,會自動生成dump,這時再輸入drwtsn32就會運行這個程序:

找到對應路徑的DMP文件就好了,通常放在以下路徑:
C:\Documents and Settings\All Users\Application Data\Microsoft\Dr Watson

 

 //-win7自動生成dump-----------------------------------------------------------------------------------------------------------------------------------------------------------------

win7下需打開regedit--> 找到:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting]

在它下面加一項LocalDumps,並作以下項配置:

 

Value 描述 Type 默認值
DumpFolder 文件保存路徑 REG_EXPAND_SZ %LOCALAPPDATA%CrashDumps
DumpCount dump文件的最大數目 REG_DWORD 10
DumpType 指定生成的dump類型:
0:Custom dump
1:Mini dump
2:Full dump
REG_DWORD 1
CustomDumpFlags 僅在DumpType爲0時使用
爲MINIDUMP_TYPE的組合
REG_DWORD
MiniDumpWithDataSegs|
MiniDumpWithUnloadedModules|
MiniDumpWithProcessThreadData





 

 

 

 

 

 

 

能夠寫成.bat:

 

[cpp]  view plain copy
 
 
  1. @echo off  
  2. echo 設置Dump...  
  3. reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps"  
  4. reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpFolder /t REG_EXPAND_SZ /d "C:\MyDump" /f  
  5. reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpType /t REG_DWORD /d 2 /f  
  6. reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpCount /t REG_DWORD /d 10 /f  
  7. echo Dump已經設置  
  8. pause  
  9. @echo on  
[cpp]  view plain copy
 
 
  1. @echo off  
  2. echo 正在取消設置Dump...  
  3. reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /f  
  4. echo Dump已經取消設置  
  5. pause  
  6. @echo on  

 

LocalDumps是全局的,若是想針對指定進程單獨設置,如test1.exe,則在/LocalDumps下新建子項test1.exe,同時在test1目錄下複製上表的選項,這樣,系統就會先讀全局設置,再讀子項test1.exe的設置

 

 

在Windows 7上能夠由多個方法產生dump文件:

轉一篇文章:

 

 

如何使用dump文件

我最近在開發一個windows下的程序(win7/win8),有一些case下會crash,若是在本身開發機器上調試比較簡單:運行程序,而後vs attach到進程上便可,可是在每臺QA的機器上安裝vs時不現實的,所以咱們要用到dump文件。

微軟網站有一篇文章講述如何建立dump文件:

http://support.microsoft.com/kb/931673

第一種: 經過任務管理器:這種適用在程序掛了(crash)的時候進程還未退出,好比我運行程序,出現了下面的錯:

此時打開任務管理器,右擊相應進程,點擊"Create Dump File「:

一會建立完成:

而後把這個DMP文件拷到開發機器上,用VS打開: 會出現下面的界面,要想知道發生錯誤時候的調用棧,須要設置symbol的路徑,點擊」Set Symbol Paths「:

注意這個pdb要對應於crash的exe,不然調用棧無法顯示:

設置完成後,點擊」Debug with Native Only「 你就能夠看到調用棧了。

 

第二種: 改註冊表

若是程序crash的時候沒有框蹦出來,能夠經過改註冊表的設置讓操做系統在程序crash的時候自動生成dump,並放到特定的目錄下

 

[plain]  view plain copy
 
 
 
  1. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps  
  2. Value Name = DumpType  
  3. Data type: REG_DWORD  
  4. Value Data = 1  


其中Value Data=1表明的含義是:

 

 

[plain]  view plain copy
 
 
 
  1. 0 = Create a custom dump  
  2. 1 = Mini dump  
  3. 2 = Full dump  


設置完成後,crash發生時,操做系統生成dump,路徑在%LOCALAPPDATA%\CrashDumps下,詳細能夠參考:

 

http://msdn.microsoft.com/en-us/library/bb787181%28v=VS.85%29.aspx

(完)

 

 

 

最簡單的方法,應用dump文件,就是修改註冊表,這樣每個程序就自動回建立dump文件;

下面給出修改註冊表的reg文件:

注意修改cdb.exe路徑,和本身計算機上的一致;

將下面的內容保存到txt文本中,而後修修改txt爲reg,而後保存,雙擊reg文件,導入到註冊表就能夠了;

 

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]"Auto"="1""Debugger"="\"D:\\Program Files\\Debugging Tools for Windows (x86)\\cdb.exe\" -p %ld -e %ld -c \".dump /ma /u C:\\crash.dmp;q\""[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]"DbgJITDebugLaunchSetting"=dword:00000002"DbgManagedDebugger"="\"D:\\Program Files\\Debugging Tools for Windows (x86)\\cdb.exe\" -p %ld -e %ld -c \".dump /ma /u C:\\crash.dmp;q\""

相關文章
相關標籤/搜索