異常屏蔽處理
2013年05月15日 ⁄ 綜合 ⁄ 共 2906字 ⁄ 字型大小 小 中 大 ⁄ 評論關閉
1。SetErrorMode(SEM_NOGPFAULTERRORBOX),這樣在出現GP錯誤時不會彈出那個對話框,但應用程序會被關閉;
2。使用SetUnhandledExcptionFilter設置最外層的異常過濾器,你可以選擇EXCEPTION_EXECUTE_HANDLER、EXCEPTION_CONTINUE_EXECUTION或EXCEPTION_CONTINUE_SEARCH;
3。將結構化異常處理__try/__except/__final或C++異常處理try/catch套在你的WinMain外面,自己處理異常。
無論如何,發生不該出現的異常而不去尋找異常的原因,而是想辦法「屏蔽」異常,不是解決問題的辦法。
========================================================================
SetUnhandledExceptionFilter 很多情況下會有無效的情況. 所以使用 seh 很多,但今天偶然發現了 vs2008 的crt版本也是引起這種情況的原因之一.
char s[9];
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );//沒用
_CrtSetReportMode( _CRT_ASSERT, 0 );//沒用
int i = 0;
//i = 5/i;
s[10000024] = '0';
strcpy(s, "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
printf("%s%d", s,i);
這在 vs2008 下是會報錯的,調試時會跳入 gs_report.c 中的 __report_gsfailure ,查了一下發現是微軟自己的 "緩衝溢出檢查" 發現有溢出就立即退出程序了. 並且會清空 SetUnhandledExceptionFilter 設置過的處理函數,具體可見其代碼:
SetUnhandledExceptionFilter(NULL);
UnhandledExceptionFilter((EXCEPTION_POINTERS *)&GS_ExceptionPointers);
--------------------------------------------------
可以關閉 "緩衝溢出檢查" 來恢復 SetUnhandledExceptionFilter 的功能. 我覺得微軟這樣做實在是過份,活生生把 SetUnhandledExceptionFilter 給廢了--至少yan割了,使得 SetUnhandledExceptionFilter 幾乎沒有存在的價值.
以下這篇文章也提到了.
http://www.diybl.com/course/1_web/webjs/20100710/408222.html
--------------------------------------------------
去除莫名其妙的CRT調用導入
去除莫名其妙的CRT調用導入
www.diybl.com 時間 : 2010-07-10 作者:網路 編輯:Mr.阿布 點擊: 39 [ 評論 ]
用上了VC9,在做DLL的時候發現即使不用到CRT函數還是會鏈上msvcr90.dll這個鳥東西。特地花了點時間研究了一下如何去掉這些多餘的調用
(1)入口點的CRT初始化
鏈接器->高級->入口點裡設定自己的DLL入口點,這樣就去掉了CRT初始化用到的一堆鳥調用。
(2)_purecall
只要有純虛函數的地方就一定會導入這麼個調用。這個東西是在調用純虛函數非法時使用的,我們可以自己定義一個,裡面的內容就是出個錯誤提示然後掛掉或者其他怎麼滴
int __cdecl _purecall (void)
{
DebugBreak();
return 0;
}
(3)delete
當導出的類里有虛的析構函數時,就會導入CRT里的delete。看了一下彙編,發現釋放對象的時候是下面這段代碼:
if (del_type & 2)
{
for (i = 0; i < N; i++)
~XXX();
delete obj;
}
else
{
~XXX();
if (del_type & 1)
delete obj;
}
上面那個是delete[]部分,下面那個是delete部分,所以重載了類里的這兩個操作符,對CRT delete的引用就會變少了。當然,重載了delete就必須重載new了。
(4)徹底消除delete和type_info::_type_info_dtor_internal_method()
全部使用了自己的delete後發現還是會引用CRT里的delete。找了一下,發現和後面那個call是一起的,似乎是用在RTTI里的。據說VS2005以後是默認打開RTTI的。反正俺們用不著,加上/GR-,上述兩位就拜拜了。
(5)C++異常
用不著時把它給關了,又去掉了一大堆CRT調用。
(6)_crt_debugger_hook
用在檢查棧溢出的函數里,只要函數的局部變數一多(譬如放個數組之類的)就會有這樣的代碼。如果確實不需要的話可以關掉緩衝區安全檢查這個選項(/GS-),可以去除這個調用。
終於,把那些莫名其妙導入的CRT調用去掉了,只剩下用到的幾個。這樣看起來比較清爽乾淨。。。。。。
====================================================
try,catch,finally執行流程
try{
//1:拋出異常的代碼
//2:代碼
}catch(){
//3:代碼
//4:拋出異常
}finally{
//5:代碼
}
//6:代碼
首先要明確的一點是:不管try是否拋出異常,finally語句塊都會執行。
小心注意6!!
整個try,catch,finally執行有以下幾種情況:
1:try語句塊沒有拋出異常。如果是這種情況,程序會執行try,finally以及finally塊之後的代碼;
2:try語句塊拋出了異常並且catch有匹配的異常。當遇到try裡面拋出的異常後,try塊裡面剩下的代碼就不執行了,跳轉到catch塊裡面。
這裡又可以分為2種情況。第一種,拋出的異常被後面的catch捕獲,而catch又沒有拋出新的異常,那麼執行順序是1356 ;第二種,如果catch裡面又拋出新的異常,順序是1345,然後將新的異常返回給方法調用者,6就不執行了 ;
3:try語句塊拋出了異常,但是後面的catch沒有能匹配的異常。那麼會執行try和finally裡面的語句也就是15,然後將該異常返回給方法調用者,不執行6 。
總結:
如果異常不能被捕捉的話,finally{}後面的語句就不會執行了,而finally{}一定被執行