windows下程序有时突然崩溃了,偶发性的崩溃很难找。于是就需要保存崩溃时的dump信息了。
下面是关于如何生成dmp文件的代码。
头文件
#pragma once #include <windows.h> #include <DbgHelp.h> #include <stdlib.h> #include <string> #pragma comment(lib, "dbghelp.lib") namespace FrameworkMiniDump { std::wstring GetTimeNowString(); std::string WStringToString(const std::wstring& str); std::wstring StringToWString(const std::string& str); std::string getexepath(); inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName); inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput); inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName); LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo); void DisableSetUnhandledExceptionFilter();// 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效 void InitMinDump(); }
源文件:
#include "MiniDump.h" #include <iostream> #include <ctime> #include <string> namespace FrameworkMiniDump { std::wstring GetTimeNowString() { time_t rawtime; struct tm * timeinfo; wchar_t buffer[80]; time(&rawtime); timeinfo = localtime(&rawtime); //wcsftime(buffer, sizeof(buffer), L"%d-%m-%Y %H:%M:%S", timeinfo); wcsftime(buffer, sizeof(buffer), L"%d-%m-%Y-%H-%M-%S", timeinfo); std::wstring str(buffer); return str; } std::wstring StringToWString(const std::string& str) { #if defined(WIN32) size_t sz = str.length(); int nd = MultiByteToWideChar(CP_ACP, 0, &str[0], sz, NULL, 0); std::wstring ret(nd, 0); int w = MultiByteToWideChar(CP_ACP, 0, &str[0], sz, &ret[0], nd); if (str.length() != sz) { throw std::exception("StringToWString Err"); } return ret; #else const char* p = str.c_str(); size_t len = str.length(); size_t sz = len * sizeof(wchar_t); wchar_t* tp = new wchar_t[sz]; size_t w = mbstowcs(tp, p, sz); if (w != len) { delete[] tp; throw std::exception("StringToWString Err"); } std::wstring ret(tp); delete[] tp; return ret; #endif } std::string WStringToString(const std::wstring& str) { size_t sz = str.length(); #if defined(WIN32) int nd = WideCharToMultiByte(CP_ACP, 0, &str[0], sz, NULL, 0, NULL, NULL); std::string ret(nd, 0); int w = WideCharToMultiByte(CP_ACP, 0, &str[0], sz, &ret[0], nd, NULL, NULL); /*if (ret.length() != sz) { throw std::exception("WStringToString Err"); }*/ return ret; #else const wchar_t* p = str.c_str(); char* tp = new char[sz]; size_t w = wcstombs(tp, p, sz); if (w != sz) { delete[] tp; throw std::exception("WStringToString Err"); } std::string ret(tp); delete[] tp; return ret; #endif } std::string getexepath() { wchar_t result[MAX_PATH]; std::wstring wstr = std::wstring(result, GetModuleFileName(NULL, result, MAX_PATH)); return WStringToString(wstr); } 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, std::wstring(L"ntdll").c_str()) == 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) { std::string exename = "Dmp"; std::wstring wexename = StringToWString(exename);; std::wstring filename = wexename + L"-" + GetTimeNowString() + L".dmp"; CreateMiniDump(pExceptionInfo, filename.c_str()); return EXCEPTION_EXECUTE_HANDLER; } // 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效 void DisableSetUnhandledExceptionFilter() { void* addr = (void*)GetProcAddress(LoadLibrary(L"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(); } }
使用:
int main() { ...... FrameworkMiniDump::InitMinDump(); ...... }
调用一下InitMinDump就可以了,这里面会注册一个回调,崩溃时会保存的dmp文件。
注意:需要在debug模式。保存下来的dmp文件,需要结合pdb文件和源代码才能定位到哪里崩溃了。具体的我也不懂。
原文地址:https://www.cnblogs.com/xcywt/p/10291219.html
时间: 2024-10-07 09:59:03