讓程序在崩潰時體面的退出之SEH+Dump文件

         在我上篇文章《讓程序在崩潰時體面的退出之SEH》中講解了SEH中try/except可以捕捉異常,避免程序的崩潰,並且可以在處理完異常之後,還能決定進該進程如何執行。對於應用程序的使用者來說,並不知道異常的發生。但是對於軟件的開發者來說,雖然避免了程序的崩潰,可是這樣可以讓程序崩潰的缺陷存在於代碼中,就像一個定時炸彈,不知道什麼時候會爆炸。要想修復這樣的缺陷,首先要找到導致程序崩潰的那行代碼。而我在我的那篇《讓程序在崩潰時體面的退出之Dump文件》裏面介紹瞭如何用Dump文件來定位使程序崩潰的代碼。這裏依然可以用同樣的方法。下面就是創建Dump文件的函數。
// 創建Dump文件
// 
void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
	// 創建Dump文件
	//
	HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	// Dump信息
	//
	MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
	dumpInfo.ExceptionPointers = pException;
	dumpInfo.ThreadId = GetCurrentThreadId();
	dumpInfo.ClientPointers = TRUE;

	// 寫入Dump文件內容
	//
	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

	CloseHandle(hDumpFile);
}

       從上面的代碼中可以看出,要想創建Dump文件,必須得到一個指向EXCEPTION_POINTERS結構的指針。怎麼在try/except塊中得到這個指針呢?這個時候就需要用到Windows API中的GetExceptionInformation()。這個函數的返回值就是一個指向EXCEPTION_POINTERS結構的指針。下面是具體的代碼。

// 作爲except塊中表達式的函數
//
LONG CrashHandler(EXCEPTION_POINTERS *pException)
{	
	// 在這裏添加處理程序崩潰情況的代碼
	//

	// 這裏以彈出一個對話框爲例子
	//
	MessageBox(NULL, _T("Message from Catch handler"), _T("Test"), MB_OK);

	// 創建Dump文件
	//
	CreateDumpFile(_T("C:\\Test.dmp"), pException);

	return EXCEPTION_EXECUTE_HANDLER;
}

int _tmain(int argc, _TCHAR* argv[])
{
	__try
	{
		MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);

		// 除零,人爲的使程序崩潰
		//
		int i = 13;
		int j = 0;
		int m = i / j;
	}
	// 捕捉到讓程序崩潰的異常時創建Dump文件
	//
	__except(CrashHandler(GetExceptionInformation()))
	{
		// 這裏以彈出一個對話框爲例子
		//
		MessageBox(NULL, _T("Message from '__except' section"), _T("Test"), MB_OK);
	}

	MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);

	return 0;
}

        編譯上面的代碼並運行,會依次彈出下面這些對話框,並在C盤創建一個Dump文件Test.dmp。

        有了Dump文件,就可以輕鬆定位使程序崩潰的那行代碼,具體方法可參考我的《讓程序在崩潰時體面的退出之Dump文件》。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章