人非圣人,孰能无措。过而改之,善莫大焉。
既然写程序就一定会有BUG,对于在一般的BUG我们可以找复现路径。但有一些特殊BUG(可能是万中无一),复现一万次也不见得能出现一次,但是又是存在的;或者当BUG发生在用户使用过程中,Dump文件就显得特别重要。
WinAPI函数介绍
Windows为Dump文件的保存提供了Api函数,需要使用Dbghelp.h 和 Dbghelp.lib,可以在MSDN中找到。
BOOL
WINAPI
MiniDumpWriteDump(
__in HANDLE hProcess, // 要生成Dump信息的进程句柄
__in DWORD ProcessId, // 要生成Dump信息的进程ID
__in HANDLE hFile, // 存储Dump信息的文件句柄
__in MINIDUMP_TYPE DumpType, // 存储Dump信息的类型
// 指向MINIDUMP_EXCEPTION_INFORMATION的指针,如果为NULL,Dump信息中将不会包含错误信息
__in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
// 指向MINIDUMP_USER_STREAM_INFORMATION的指针,如果为NULL,Dump信息中将不会包含用户定义的信息
__in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
// 指向MINIDUMP_CALLBACK_INFORMATION的指针,一个回调函数,用于处理Dump信息。如果为空怎不处理。
__in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
备注:
hProcess:这个句柄需要PROCESS_QUERY_INFORMATION和PROCESS_VM_READ权限,如果要收集句柄信息还需要PROCESS_DUP_HANDLE权限。
DumpType:这个参数可以是一个或多个MINIDUMP_TYPE类型的枚举。
typedef enum _MINIDUMP_TYPE {
MiniDumpNormal, // 跟踪进程中活动线程的堆栈的必要信息
MiniDumpWithDataSegs,
MiniDumpWithFullMemory,
MiniDumpWithHandleData,
MiniDumpFilterMemory,
MiniDumpScanMemory,
MiniDumpWithUnloadedModules,
MiniDumpWithIndirectlyReferencedMemory,
MiniDumpFilterModulePaths,
MiniDumpWithProcessThreadData,
MiniDumpWithPrivateReadWriteMemory,
MiniDumpWithoutOptionalData,
MiniDumpWithFullMemoryInfo,
MiniDumpWithThreadInfo,
MiniDumpWithCodeSegs,
MiniDumpWithoutAuxiliaryState,
MiniDumpWithFullAuxiliaryState,
MiniDumpWithPrivateWriteCopyMemory,
MiniDumpIgnoreInaccessibleMemory,
MiniDumpWithTokenInformation,
MiniDumpWithModuleHeaders,
MiniDumpFilterTriage,
MiniDumpWithAvxXStateContext,
MiniDumpWithIptTrace,
MiniDumpValidTypeFlags,
MiniDumpScanInaccessiblePartialPages
} MINIDUMP_TYPE;
Demo
1、创建Dump文件
BOOL createDumpFile(PEXCEPTION_POINTERS pExceptionInfo)
{
QString strDumpFile = QString("%1.dmp").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss"));
HANDLE hFile = CreateFile(
strDumpFile.toStdWString().c_str(),
GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
// write the dump
BOOL bOK = MiniDumpWriteDump(
GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
CloseHandle(hFile);
return bOK;
}
return false;
}
2、在程序崩溃时调用
讨论一个问题,程序为什么会崩溃嗯?系统是在什么时候弹出程序崩溃提示的?
程序崩溃的发生就是程序中出现了没有被捕获的异常。
处理程序崩溃我们就需要用到一个API函数SetUnhandledExceptionFilter。
这个API也常用于让自己的程序死的体面。
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter (
// 函数指针,用于处理异常
_In_LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
) ;
long __stdcall lpTopLevelExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
createDumpFile(pExceptionInfo);
return 0;
}