dump

#ifndef  DUMP_HEAD_FILE
#define  DUMP_HEAD_FILE
#pragma once

#include <windows.h>
#include <imagehlp.h>
#include <stdlib.h>
#include <tchar.h>
#include <stdio.h>
#include <assert.h>


#pragma comment(lib, "dbghelp.lib")
#pragma warning(disable:4996) 
#define CountArray(Array) (sizeof(Array)/sizeof(Array[0]))


//运行异常处理
void RunCrashHandler(void);

//注销异常处理
void RemoveCrashHandler(void);

#endif


#include "stdafx.h"
#include "dump.h"

PVOID   VectorHandle = NULL;

inline BOOL IsDataSectionNeeded(const TCHAR* pModuleName)
{
	if (pModuleName == 0)return FALSE;
	TCHAR szFileName[_MAX_FNAME] = { 0 };
	_tsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
	if (_tcsicmp(szFileName, TEXT("ntdll")) == 0)
		return TRUE;
	assert(FALSE);
	return FALSE;
}

inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT  pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput)
{
	assert(pInput);
	assert(pOutput);
	if (pInput == 0 || pOutput == 0)return FALSE;

	switch (pInput->CallbackType)
	{
	case ModuleCallback:
		if (pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
			if (!IsDataSectionNeeded((TCHAR*)pInput->Module.FullPath))
				pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
	case IncludeModuleCallback:
	case IncludeThreadCallback:
	case ThreadCallback:
	case ThreadExCallback:
		return TRUE;
	default:;
	}
	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);
	assert(hFile);
	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);
	}
	return;
}



//vect异常处理回调函数
LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
{

	TCHAR szText[128] = { 0 };
#ifdef _DEBUG
	switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
	{
	case EXCEPTION_ACCESS_VIOLATION:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 线程试图读取或写入到虚拟地址对于其不具有适当的访问------%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图访问数组元素,是出界和底层硬件支持的边界检查。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_BREAKPOINT:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  断点遇到。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_DATATYPE_MISALIGNMENT:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图读取或写入该未对准的硬件上不提供对准数据。例如,16位的值必须在2字节边界对齐; 32位值4字节的边界上,等等。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_DENORMAL_OPERAND:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 一个在浮点运算的操作数是反常值。规格化值是太小,无法表示为标准浮点值。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图通过零浮点除数划分一个浮点值。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_INEXACT_RESULT:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 浮点运算的结果不能被精确表示作为一个小数。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_INVALID_OPERATION:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 此异常表示不包括在此列表中的任何浮点异常。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_OVERFLOW:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 浮点运算的指数大于由相应的类型所允许的幅度。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_STACK_CHECK:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 堆栈溢出或下溢作为浮点运算的结果。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_FLT_UNDERFLOW:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 浮点运算的指数小于由相应类型所允许的幅度。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_ILLEGAL_INSTRUCTION:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图执行一个无效的指令。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_IN_PAGE_ERROR:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图访问一个网页,不存在,并且该系统无法加载的页面。例如,如果在运行程序通过网络失去网络连接,可能会出现这种异常。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图通过的零的整数除数划分的整数值。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_INT_OVERFLOW:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  的整数运算的结果所引起的进位出来的结果的最显著位。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_INVALID_DISPOSITION:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  异常处理程序返回了一个无效配置的异常分派。使用高级语言编程如C应该永远不会遇到此异常。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_NONCONTINUABLE_EXCEPTION:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 线程试图继续发生不可持续异常后执行。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_PRIV_INSTRUCTION:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  线程试图执行一条指令,其操作在当前机器模式是不允许的。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_SINGLE_STEP:
		{
			_sntprintf(szText, CountArray(szText), TEXT("  一丝丝陷阱或其他单指令的机制标志着一个指令已被执行。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	case EXCEPTION_STACK_OVERFLOW:
		{
			_sntprintf(szText, CountArray(szText), TEXT(" 线程用完它的堆栈。-----%0x\n"), ExceptionInfo->ExceptionRecord->ExceptionAddress);
			MessageBox(NULL, szText, TEXT("提示"), MB_OK);
			OutputDebugString(szText);
		}
		break;
	default:
		break;
	}
#endif
	return EXCEPTION_CONTINUE_SEARCH;
}


//异常处理回调函数
LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException)
{
	//定义变量
	TCHAR szModuFile[MAX_PATH] = { 0 };
	TCHAR szDumpFileName[MAX_PATH] = { 0 };

	//获取模块路径
	GetModuleFileName(NULL, szModuFile, MAX_PATH);

	//获取时间
	SYSTEMTIME time;
	GetLocalTime(&time);
	_sntprintf_s(szDumpFileName, CountArray(szDumpFileName), TEXT("%s%d%d%d%d%d.dmp"), szModuFile, time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute);

	//创建dump文件
	CreateMiniDump(pException, szDumpFileName);

	return EXCEPTION_CONTINUE_SEARCH;
}

//运行异常处理
void RunCrashHandler(void)
{
	//设置异常处理回调函数 
	SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
	if (VectorHandle==NULL)
	{
		//注册vect异常处理程序
		VectorHandle = AddVectoredExceptionHandler(0, VectoredHandler);
		assert(VectorHandle != NULL);
	}
	return;
}

//注销异常处理
void RemoveCrashHandler(void)
{
	
	if(VectorHandle)
	{
		RemoveVectoredExceptionHandler(VectorHandle);
	}
	
	return ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值