处理 程序异常崩溃后的善后工作


好像以前面试被问过,没回答出来,但一直没用到过,也就没研究。

今天看了些代码,发现要实现崩溃后的处理,竟然很简单。

看来很多东西只是见没见过,没见过觉得很神奇,见过了其实也没啥。


要实现程序异常崩溃后的善后工作:包括当时堆栈情况-内存空间数据、是否重启登,只需要调用SetUnhandledExceptionFilter这个函数就可以了。

实现:

1、在程序刚启动时,设置未捕获异常的处理函数

    为什么呢?程序崩溃就是因为有些异常没有被捕获到,如果你设置了SetUnhandledExceptionFilter,这些异常会被其所定义的函数处理,如果没设置,就会调用windows默认处理方式,询问是否发生信息云云,然则啥用也没有。

比如 main 或winmain开始处

::SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

2、崩溃处理的处理

比如写dump文件,重启程序

#pragma once
#include "shared/util.h"
#include <DbgHelp.h>

BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output)
{
	if(input == NULL || output == NULL)
		return FALSE;

	BOOL ret = FALSE;
	switch(input->CallbackType)
	{
	case IncludeModuleCallback:
	case IncludeThreadCallback:
	case ThreadCallback:
	case ThreadExCallback:
		ret = TRUE;
		break;
	case ModuleCallback:
		{
			if( !(output->ModuleWriteFlags & ModuleReferencedByMemory) )
			{
				output->ModuleWriteFlags &= ~ModuleWriteModule;
			}
			ret = TRUE;
		}
		break;
	default:
		break;
	}

	return ret;
}

void WriteDump(EXCEPTION_POINTERS* exp, const std::wstring &path)
{
	HANDLE h = ::CreateFile(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, 
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	MINIDUMP_EXCEPTION_INFORMATION info;
	info.ThreadId = ::GetCurrentThreadId();
	info.ExceptionPointers = exp;
	info.ClientPointers = NULL;

	MINIDUMP_CALLBACK_INFORMATION mci; 
	mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback; 
	mci.CallbackParam = 0; 

	MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory); 

	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, mdt, &info, NULL, &mci);
	::CloseHandle(h);
}
//自定义的异常处理
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* exp)
{
	nbase::Time::TimeStruct qt = nbase::Time::Now().ToTimeStruct(true);
	std::wstring file = nbase::StringPrintf(L"%04d%02d%02d_%02d%02d%02d.dmp", 
		qt.year_, qt.month_, qt.day_of_month_, qt.hour_, qt.minute_, qt.second_);
	std::wstring dir = QPath::GetLocalAppDataDir(APP_DATA_DIR);
	dir.append(file);

	WriteDump(exp, dir);

	QCommand::RestartApp(L"/" CMD_APP_CRASH L" 1");

	return EXCEPTION_EXECUTE_HANDLER;
}


猜你喜欢

转载自blog.csdn.net/shuilan0066/article/details/80987762
今日推荐