捕获未经处理的异常
目的
程序在异常捕获中难免会遇到未经捕获的异常,因此要在最上级对未抓取异常进行处理,包括保存用户文件及输出Dmp文件,Dmp文件可以帮助开发人员快速定位异常所在具体工具可以利用VisualStudio或者Windbg工具来跟踪定位异常抛出语句。
举个例子,office系列Word大家都用过,如果遇到崩溃退出,你所敲过的文字office是会给你保存下来的不会丢失,这就是要讲的内容。当然现在office很少出现崩溃了
关键API
SetUnhandledExceptionFilter();
具体操作
LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExInfo)
{
//未经处理会跳转到此处
}
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
完整代码输出Dump文件
头文件内容
#pragma once
class ExceptionDmp
{
public:
ExceptionDmp();
~ExceptionDmp();
};
源文件内容
LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExInfo)
{
TCHAR dmp_path[MAX_PATH];
::GetTempPath(_countof(dmp_path), dmp_path);
SYSTEMTIME tm;
GetLocalTime(&tm);//获取时间
TCHAR file_name[128];
_stprintf_s(file_name, L"%spbim%d-%02d-%02d-%02d-%02d-%02d.dmp", dmp_path,
tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);//设置dmp文件名称
HANDLE hFile = CreateFile(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION info;//构造dmp异常数据结构
info.ThreadId = GetCurrentThreadId();
info.ClientPointers = FALSE;
info.ExceptionPointers = pExInfo;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
(MINIDUMP_TYPE)MiniDumpNormal, &info, NULL, NULL);//写dmp文件
CloseHandle(hFile);
const TCHAR *fmt =
{
L"遇到问题需要关闭,您的数据有可能丢失,\n\n"
L"我们对此引起的不便表示抱歉;请将\n\n"
L"\"%s\"\n\n"
L"发送给我们以便快速查找问题之所在,谢谢。\n\n"
L"邮箱:************\n\n"
L"电话:***-****-***"
};
TCHAR msg[400];
_stprintf_s(msg, fmt, file_name);
MessageBox(NULL, msg, L"程序异常报告", MB_ICONERROR | MB_SYSTEMMODAL);
}
else
{
TCHAR info[300] = { L"fail to create dump file:" };
_tcscat(info, file_name);
MessageBox(NULL, info, L"dump", MB_ICONERROR | MB_SYSTEMMODAL);
}
return EXCEPTION_EXECUTE_HANDLER;
}
ExceptionDmp::ExceptionDmp()
{
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
}
static ExceptionDmp s_ExceptionDmp;
ExceptionDmp::~ExceptionDmp()
{
}
注册入口由静态堆变量 s_ExceptionDmp
触发构造函数进行API调用;
关键步骤加了注释,教程到此结束。
请记住崩溃转储的价值往往比1000个甚至更多的bug报告更有意义