C++之程序奔溃创建DUMP文件(VS2015)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zl_95520/article/details/82985273

创建DUMP文件

直接上干货!

注意一下自己VS的版本!以及编译平台!

//本程序是基于 VS2015 版本,X86 !!!
//创建头文件DumpFile.h, 将下列代码放进文件中

#pragma once
#include <windows.h>
#include <Dbghelp.h>
#include <iostream>  
#include <vector>  
#include <tchar.h>
using namespace std;


#pragma comment(lib, "Dbghelp.lib")


namespace NSDumpFile
{
	void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
	{
		// 创建Dump文件  
		HANDLE hDumpFile = CreateFile(((LPCSTR)lpstrDumpFilePathName), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);


		// Dump信息  
		MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
		dumpInfo.ExceptionPointers = pException;
		dumpInfo.ThreadId = GetCurrentThreadId();
		dumpInfo.ClientPointers = TRUE;


		// 写入Dump文件内容  
		MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);


		CloseHandle(hDumpFile);
	}


	LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
	{
		return NULL;
	}


	BOOL PreventSetUnhandledExceptionFilter()
	{
		//Windows 本身的32位的动态链接库,确保自己有这个库
		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;
			//这边是生成的DUMP文件的名称
			_tcscat(szMbsFile, _T("CrashDumpFile.dmp"));
			CreateDumpFile((LPCWSTR)szMbsFile, pException);
		}


		//这边提示的消息可根据自己的需求设计
		// TODO: MiniDumpWriteDump
		MessageBox(NULL,_T("***又双叒叕崩溃了,惊不惊喜?意不意外?***"),_T("错误"),MB_OK);
		//FatalAppExit(-1, _T("***又双叒叕崩溃了,惊不惊喜?意不意外?***"));
		return EXCEPTION_CONTINUE_SEARCH;
	}


	void RunCrashHandler()
	{
		SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
		PreventSetUnhandledExceptionFilter();
	}
};


#define DeclareDumpFile() NSDumpFile::RunCrashHandler();

然后再自己主程序中(建议在开头)添加 DeclareDumpFile() ,一旦软件运行奔溃,可直接定位到对应代码奔溃处

再唠叨一句

生成的DUMP文件只适用于对应软件的版本,也是说需要生成DUMP文件后,最好保存对应的符号文件以及可执行文件(.exe)!一旦你再次编译自已的程序,就算程序内容没变,之前生成的DUMP文件也无法使用了!

猜你喜欢

转载自blog.csdn.net/zl_95520/article/details/82985273