天天看點

用CrashDump定位應用錯誤

用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檔案而被定位。可以說是非常高效的定位問題所在的方法之一。:)