人非圣人邪乍,孰能無(wú)措降狠。過(guò)而改之,善莫大焉庇楞。
既然寫(xiě)程序就一定會(huì)有BUG榜配,對(duì)于在一般的BUG我們可以找復(fù)現(xiàn)路徑。但有一些特殊BUG(可能是萬(wàn)中無(wú)一)吕晌,復(fù)現(xiàn)一萬(wàn)次也不見(jiàn)得能出現(xiàn)一次蛋褥,但是又是存在的;或者當(dāng)BUG發(fā)生在用戶使用過(guò)程中聂使,Dump文件就顯得特別重要壁拉。
WinAPI函數(shù)介紹
Windows為Dump文件的保存提供了Api函數(shù),需要使用Dbghelp.h 和 Dbghelp.lib柏靶,可以在MSDN中找到。
BOOL
WINAPI
MiniDumpWriteDump(
__in HANDLE hProcess, // 要生成Dump信息的進(jìn)程句柄
__in DWORD ProcessId, // 要生成Dump信息的進(jìn)程ID
__in HANDLE hFile, // 存儲(chǔ)Dump信息的文件句柄
__in MINIDUMP_TYPE DumpType, // 存儲(chǔ)Dump信息的類(lèi)型
// 指向MINIDUMP_EXCEPTION_INFORMATION的指針溃论,如果為NULL屎蜓,Dump信息中將不會(huì)包含錯(cuò)誤信息
__in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
// 指向MINIDUMP_USER_STREAM_INFORMATION的指針,如果為NULL钥勋,Dump信息中將不會(huì)包含用戶定義的信息
__in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
// 指向MINIDUMP_CALLBACK_INFORMATION的指針炬转,一個(gè)回調(diào)函數(shù),用于處理Dump信息算灸。如果為空怎不處理扼劈。
__in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
備注:
hProcess:這個(gè)句柄需要PROCESS_QUERY_INFORMATION和PROCESS_VM_READ權(quán)限,如果要收集句柄信息還需要PROCESS_DUP_HANDLE權(quán)限菲驴。
DumpType:這個(gè)參數(shù)可以是一個(gè)或多個(gè)MINIDUMP_TYPE類(lèi)型的枚舉荐吵。
typedef enum _MINIDUMP_TYPE {
MiniDumpNormal, // 跟蹤進(jìn)程中活動(dòng)線程的堆棧的必要信息
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;
原文見(jiàn):MSDN-MINIDUMP_TYPE
Demo
1、創(chuàng)建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、在程序崩潰時(shí)調(diào)用
討論一個(gè)問(wèn)題先煎,程序?yàn)槭裁磿?huì)崩潰嗯贼涩?系統(tǒng)是在什么時(shí)候彈出程序崩潰提示的?
程序崩潰的發(fā)生就是程序中出現(xiàn)了沒(méi)有被捕獲的異常薯蝎。
處理程序崩潰我們就需要用到一個(gè)API函數(shù)SetUnhandledExceptionFilter遥倦。
這個(gè)API也常用于讓自己的程序死的體面。
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter (
// 函數(shù)指針占锯,用于處理異常
_In_LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
) ;
long __stdcall lpTopLevelExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
createDumpFile(pExceptionInfo);
return 0;
}