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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

编写的windows程序,崩溃时产生crash dump文件的办法

發布時間:2023/12/20 windows 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 编写的windows程序,崩溃时产生crash dump文件的办法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、引言

dump文件是C++程序發生異常時,保存當時程序運行狀態的文件,是調試異常程序重要的方法,所以程序崩潰時,除了日志文件,dump文件便成了我們查找錯誤的最后一根救命的稻草。windows程序產生dump文件和linux程序產生dump文件的方式不一樣,linux默認是不讓產生core dump文件,只要在用戶自己的~/.bash_profile文件中增加

ulimit -S -c unlimited > /dev/null 2>&1

這樣程序崩潰就可以產生可調試的core dump文件了。但是windows環境就得寫代碼才能實現了。

二、原理

windows程序當遇到異常,沒有try-catch或者try-catch也無法捕獲到的異常時,程序就會自動退出,如果這時候沒有dump文件的話,我們是沒有得到任何程序退出的信息。在windows程序異常退出之前,會預先調用一個在程序中注冊的異常處理回調函數(默認是沒有設置),只要我們在這個回調函數中調用MiniDumpWriteDump函數就可以產生我們想要的dump文件。

三、實現

1.調用SetUnhandledExceptionFilter注冊一個自定義的異常處理回調函數

SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

異常處理回調函數的原型

LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);

2.CreateFile創建dump文件,調用MiniDumpWriteDump函數往dump文件寫異常信息

[cpp]?view plain?copy ?print?
  • inline?void?CreateMiniDump(PEXCEPTION_POINTERS?pep,?LPCTSTR?strFileName)??
  • {??
  • ????HANDLE?hFile?=?CreateFile(strFileName,?GENERIC_READ?|?GENERIC_WRITE,??
  • ????????FILE_SHARE_WRITE,?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?????=?NULL;??
  • ??
  • ????????MINIDUMP_CALLBACK_INFORMATION?mci;??
  • ????????mci.CallbackRoutine?????=?(MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;??
  • ????????mci.CallbackParam???????=?0;??
  • ??
  • ????????::MiniDumpWriteDump(::GetCurrentProcess(),?::GetCurrentProcessId(),?hFile,?MiniDumpNormal,?(pep?!=?0)???&mdei?:?0,?NULL,?&mci);??
  • ??
  • ????????CloseHandle(hFile);??
  • ????}??
  • }??

  • CreateMiniDump函數是在異常處理回調函數MyUnhandledExceptionFilter中調用的

    [cpp]?view plain?copy ?print?
  • LONG?__stdcall?MyUnhandledExceptionFilter(PEXCEPTION_POINTERS?pExceptionInfo)??
  • {??
  • ????CreateMiniDump(pExceptionInfo,?"core.dmp");??
  • ??
  • ????return?EXCEPTION_EXECUTE_HANDLER;??
  • }??

  • 3.將SetUnhandledExceptionFilter失效

    vs2005中,編譯的過程中,編譯器會自動給你的程序加上一句SetUnhandledExceptionFilter(NULL),這就會導致你之前自定義的

    SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

    無效,就有可能不會產生dump文件,因此我們必須在自定義的SetUnhandledExceptionFilter之后,讓之后調用的SetUnhandledExceptionFilter無效。增加以下代碼:

    [cpp]?view plain?copy ?print?
  • //?此函數一旦成功調用,之后對?SetUnhandledExceptionFilter?的調用將無效??
  • void?DisableSetUnhandledExceptionFilter()??
  • {??
  • ????void*?addr?=?(void*)GetProcAddress(LoadLibrary("kernel32.dll"),??
  • ????????"SetUnhandledExceptionFilter");??
  • ??
  • ????if?(addr)??
  • ????{??
  • ????????unsigned?char?code[16];??
  • ????????int?size?=?0;??
  • ??
  • ????????code[size++]?=?0x33;??
  • ????????code[size++]?=?0xC0;??
  • ????????code[size++]?=?0xC2;??
  • ????????code[size++]?=?0x04;??
  • ????????code[size++]?=?0x00;??
  • ??
  • ????????DWORD?dwOldFlag,?dwTempFlag;??
  • ????????VirtualProtect(addr,?size,?PAGE_READWRITE,?&dwOldFlag);??
  • ????????WriteProcessMemory(GetCurrentProcess(),?addr,?code,?size,?NULL);??
  • ????????VirtualProtect(addr,?size,?dwOldFlag,?&dwTempFlag);??
  • ????}??
  • }??

  • 最終代碼整理:

    //minidump.h

    [cpp]?view plain?copy ?print?
  • #pragma?once??
  • #include?<windows.h>??
  • #include?<DbgHelp.h>??
  • #include?<stdlib.h>??
  • #pragma?comment(lib,?"dbghelp.lib")??
  • ??
  • #ifndef?_M_IX86??
  • #error?"The?following?code?only?works?for?x86!"??
  • #endif??
  • ??
  • 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);??
  • ????case?IncludeModuleCallback:??
  • ????case?IncludeThreadCallback:??
  • ????case?ThreadCallback:??
  • ????case?ThreadExCallback:??
  • ????????return?TRUE;??
  • ????default:;??
  • ????}??
  • ??
  • ????return?FALSE;??
  • }??
  • ??
  • inline?void?CreateMiniDump(PEXCEPTION_POINTERS?pep,?LPCTSTR?strFileName)??
  • {??
  • ????HANDLE?hFile?=?CreateFile(strFileName,?GENERIC_READ?|?GENERIC_WRITE,??
  • ????????FILE_SHARE_WRITE,?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?????=?NULL;??
  • ??
  • ????????MINIDUMP_CALLBACK_INFORMATION?mci;??
  • ????????mci.CallbackRoutine?????=?(MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;??
  • ????????mci.CallbackParam???????=?0;??
  • ??
  • ????????::MiniDumpWriteDump(::GetCurrentProcess(),?::GetCurrentProcessId(),?hFile,?MiniDumpNormal,?(pep?!=?0)???&mdei?:?0,?NULL,?&mci);??
  • ??
  • ????????CloseHandle(hFile);??
  • ????}??
  • }??
  • ??
  • LONG?__stdcall?MyUnhandledExceptionFilter(PEXCEPTION_POINTERS?pExceptionInfo)??
  • {??
  • ????CreateMiniDump(pExceptionInfo,?"core.dmp");??
  • ??
  • ????return?EXCEPTION_EXECUTE_HANDLER;??
  • }??
  • ??
  • //?此函數一旦成功調用,之后對?SetUnhandledExceptionFilter?的調用將無效??
  • void?DisableSetUnhandledExceptionFilter()??
  • {??
  • ????void*?addr?=?(void*)GetProcAddress(LoadLibrary("kernel32.dll"),??
  • ????????"SetUnhandledExceptionFilter");??
  • ??
  • ????if?(addr)??
  • ????{??
  • ????????unsigned?char?code[16];??
  • ????????int?size?=?0;??
  • ??
  • ????????code[size++]?=?0x33;??
  • ????????code[size++]?=?0xC0;??
  • ????????code[size++]?=?0xC2;??
  • ????????code[size++]?=?0x04;??
  • ????????code[size++]?=?0x00;??
  • ??
  • ????????DWORD?dwOldFlag,?dwTempFlag;??
  • ????????VirtualProtect(addr,?size,?PAGE_READWRITE,?&dwOldFlag);??
  • ????????WriteProcessMemory(GetCurrentProcess(),?addr,?code,?size,?NULL);??
  • ????????VirtualProtect(addr,?size,?dwOldFlag,?&dwTempFlag);??
  • ????}??
  • }??
  • ??
  • void?InitMinDump()??
  • {??
  • ????//注冊異常處理函數??
  • ????SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);??
  • ??
  • ????//使SetUnhandledExceptionFilter??
  • ????DisableSetUnhandledExceptionFilter();??
  • }??

  • 4.測試代碼

    //test.cpp

    [cpp]?view plain?copy ?print?
  • #include?<iostream>??
  • #include?"minidump.h"??
  • void?test()??
  • {??
  • ????std::string?s?=?"abcd";??
  • ??
  • ????try{??
  • ????????s[100]?=?'b';??
  • ????}??
  • ????catch(std::exception&?e)??
  • ????{??
  • ????????std::cout?<<?"with?exception:["?<<?e.what()?<<?"]"?<<?std::endl;??
  • ????}??
  • ????catch(...)??
  • ????{??
  • ????????std::cout?<<?"with?unknown?exception"?<<?std::endl;??
  • ????}??
  • }??
  • ??
  • void?main()??
  • {??
  • ????InitMinDump();??
  • ??
  • ????test();??
  • ??
  • ????system("pause");??
  • }??
  • 總結

    以上是生活随笔為你收集整理的编写的windows程序,崩溃时产生crash dump文件的办法的全部內容,希望文章能夠幫你解決所遇到的問題。

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