好像以前面试被问过,没回答出来,但一直没用到过,也就没研究。
今天看了些代码,发现要实现崩溃后的处理,竟然很简单。
看来很多东西只是见没见过,没见过觉得很神奇,见过了其实也没啥。
要实现程序异常崩溃后的善后工作:包括当时堆栈情况-内存空间数据、是否重启登,只需要调用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;
}