生活随笔
收集整理的這篇文章主要介紹了
让程序在崩溃时体面的退出之SEH
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??????? SEH的全稱是Structured Exception Handling,是Windows操作系統提供的一種異常處理方式。SEH是屬于操作系統的特性,不為特定語言設計,從它的名字就能看出它是一種結構化的異常處理方式。SEH包括了2個部分:終止處理__try/__finally和異常處理__try/__except,下面分別進行介紹。
??????? 終止處理__try/__finally ??????? __try/__finally可以保證無論try塊內的代碼執行結果如何,finally塊內的代碼總會被調用和執行。現在用下面的這個VC++中的控制臺程序來說明。
[cpp] view plaincopy
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;?? ????}?? ????__finally ?? ????{?? ?????????? ?????????? ?? ?????????? ?????????? ????????MessageBox(NULL,?_T("Message?from?'__finally'?section" ),?_T("Test" ),?MB_OK);?? ????}?? ?? ????MessageBox(NULL,?_T("Funcation?completed" ),?_T("Test" ),?MB_OK);?? ?? ????return ?0;?? }??
??????? 編譯上面的代碼。運行生成的EXE,會彈出下面的對話框。
??????? 點擊OK按鈕后,程序會崩潰。
??????? 在出現上面這個對話框的時候點擊Cancel,將控制權返還給程序,那么下面的對話框就會彈出。
??????? 點擊OK按鈕后,程序正常退出。 ??????? 由上面的例子可以看出,無論try塊中的代碼會不會出現異常,在程序終止的時候,finally塊中的代碼都會被調用和執行。所以一般情況下,finally塊中的代碼都是用來做一些清理工作和資源的釋放。
??????? 異常處理__try/__except ??????? __try/__except是用來捕捉異常的,只有當try塊中的代碼出現異常的時候,except塊中的代碼才會被調用和執行。它的語法是這樣的:
[cpp] view plaincopy
__try ??{?? ?????? }?? __except(expression)?? {?? ??????? }??
??????? 它最大的一個好處就是可以完全控制異常進程。expression的值決定了異常被處理完后,進程該如何執行。下面依然用VC++中的控制臺程序來說明。
[cpp] view plaincopy
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;?? ????}?? ????__except(EXCEPTION_EXECUTE_HANDLER)?? ????{?? ?????????? ?????????? ?? ?????????? ?????????? ????????MessageBox(NULL,?_T("Message?from?'__except'?section" ),?_T("Test" ),?MB_OK);?? ????}?? ?? ????MessageBox(NULL,?_T("Funcation?completed" ),?_T("Test" ),?MB_OK);?? ?? ????return ?0;?? }??
??????? 編譯上面的代碼。運行生成的EXE,會依次彈出下面的對話框。
??????? 可以看出,在異常處理代碼被調用執行后(except塊中的代碼),程序繼續可以繼續運行,并正常退出,并沒有崩潰!通過使用__try/__except可以捕捉到任何類型的異常,并保證程序不會崩潰!(想想這是多么的神奇,一個程序永遠不會崩潰!) ??????? 下面解釋一下except中表達式各個值的含義:
EXCEPTION_CONTINUE_SEARCH??????? 異常沒有被處理,繼續向上拋出。如果更上層的代碼沒有異常捕捉機制,程序就會崩潰。 EXCEPTION_CONTINUE_EXECUTION?? 異常已經被處理,返回異常發生的地方繼續執行。 EXCEPTION_EXECUTE_HANDLER??????? 異常已經被處理,程序繼續往后執行。
??????? 通過上面的例子可以知道,SEH的異常處理跟C++的異常處理不同,C++的try/catch不能控制異常進程,對于異常,要么處理,要么繼續向上拋出。而SEH卻能完全控制異常進程,處理完異常之后,還能決定進該進程如何執行。只要SEH運用得當,編寫一個永不崩潰的應用程序成為可能。但是SEH有一個致命的弱點,那就是它是一種結構化的異常處理,所以不支持面向對象 。下面用具體的VC++控制臺程序來說明。
[cpp] view plaincopy
?? ?? class ?CrashTest??{?? public :??????CrashTest()?{}?? ????~CrashTest()?{}?? ?? ????void ?Test()??? ????{??? ????????Crash();??? ????}?? ?? private :??????void ?Crash()??? ????{??? ?????????? ?????????? ????????int ?i?=?13;?? ????????int ?j?=?0;?? ????????int ?m?=?i?/?j;?? ????}?? };?? ?? int ?_tmain(int ?argc,?_TCHAR*?argv[])??{?? ????__try ?? ????{?? ????????CrashTest?test;?? ????????test.Test();?? ????}?? ????__except(EXCEPTION_EXECUTE_HANDLER)?? ????{?? ?????????? ?????????? ????}?? ?? ????return ?0;?? }??
??????? 上面的代碼不能通過編譯,VC++編譯器會給出這樣的錯誤信息:error C2712: Cannot use __try in functions that require object unwinding 。錯誤原因很簡單,try塊內使用了對象。 ??????? 要想解決這個問題,可以把使用對象的邏輯放到一個函數里,然后在try里調用這個函數,來騙過編譯器。把上面的代碼修改成下面這樣就可以通過編譯。
[cpp] view plaincopy
void ?Test()??{?? ????CrashTest?test;?? ????test.Test();?? }?? ?? int ?_tmain(int ?argc,?_TCHAR*?argv[])??{?? ????__try ?? ????{?? ????????Test();?? ????}?? ????__except(EXCEPTION_EXECUTE_HANDLER)?? ????{?? ?????????? ?????????? ????}?? ?? ????return ?0;?? }?
總結
以上是生活随笔 為你收集整理的让程序在崩溃时体面的退出之SEH 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。