用CrashDump定位應用錯誤
通常,在驅動的世界裡面,一旦我們的驅動有BUG,導緻系統藍屏,往往我們需要靠OS生成的CrashDump檔案來進行事後分析。但是事實上我們針對應用程式同樣也能生成CrashDump。在某些情形下,我們必須在應用中主動生成CrashDump,因為抓取Crash條件的時機稍縱即逝,再也難以複原Crash場景。本文要介紹的乃是
BOOL WINAPI MiniDumpWriteDump(
__in HANDLE
hProcess,
__in DWORD
ProcessId,
hFile,
__in MINIDUMP_TYPE
DumpType,
__in PMINIDUMP_EXCEPTION_INFORMATION
ExceptionParam,
__in PMINIDUMP_USER_STREAM_INFORMATION
UserStreamParam,
__in PMINIDUMP_CALLBACK_INFORMATION
CallbackParam
);
這個函數。通過運用這個函數,我們能在異常發生的時間點将整個應用的運作上下文捕捉下來。進而提供異常發生時刻的重要情報資訊。
這個函數的用法大緻如下
int WINAPI CreateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
BOOL bMiniDumpSuccessful;
CHAR szFileName[MAX_PATH];
HANDLE hDumpFile;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
…
snprintf( szFileName, MAX_PATH,“你的CrashDump檔案名”);
<- 注意:異常會多次發生,每次的原因不見得一樣,是以最好檔案名裡面附帶上崩潰發生的時間,以便協查。
hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
if (hDumpFile != INVALID_HANDLE_VALUE)
ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = TRUE;
bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile,
MiniDumpWithDataSegs|MiniDumpWithProcessThreadData|MiniDumpWithHandleData|MiniDumpWithUnloadedModules <-
注意:這個參數組合能保留一定的資料段資訊,捕捉整個程序的記憶體鏡像也是個辦法,但是一般情況下,有一定的資料就可以了,真正關鍵的部分是棧裡面保留的函數調用棧。用于定位異常發生時刻有哪些函數被牽扯進來。
, &ExpParam, NULL, NULL);
CloseHandle(hDumpFile);
}
else
OutputDebugString("xxx -- Can not create crash dump!!!\n");
<- CrashDump如果都寫不出來,認命吧。
ExitProcess(pExceptionPointers->ExceptionRecord->ExceptionCode);
<- 異常都發生了,還是不要讓應用繼續跑下去為妙。不然出其他的婁子就更難判斷了。
上面介紹的函數如何觸發呢?比較通俗的寫法是
LPTOP_LEVEL_EXCEPTION_FILTER defaultExceptionCallBack = NULL;
int main(int argc,char **argv)
。。。
defaultExceptionCallBack = SetUnhandledExceptionFilter(&CreateDump);
該幹嘛幹嘛
在所有人都不接管異常的情況下,CreateDump會得到觸發,這麼一來,異常的場景就能被捕捉到。哪些非常難以再現的場景就有辦法得到重制或者定位。
最近數年間的現場緊急支援中,有95%以上的case通過應用崩潰時刻的dump檔案而被定位。可以說是非常高效的定位問題所在的方法之一。:)