paip.c++ gcc 不能捕獲exception異常的解決

來源:互聯網
上載者:User

paip.c++ gcc 不能捕獲exception異常的解決


作者Attilax ,  EMAIL:1466519819@qq.com 
來源:attilax的專欄
地址:http://blog.csdn.net/attilax




現象:
////////////
不能捕獲 "index out of range", 下標越界異常...經過測試,只能捕獲手動throw出來的異常..使用windows的__try   ____except,,QT 的QT_try QT_catch 都是不行..


原因"
////////////////
c++標準  try, catch, throw是C++標準裡的文法,標準只要求try catch捕獲throw出來的異常,並不要求捕獲系統異常(如被0除,段錯誤,CPU異常等)。從C++層面來說,不要期望try, catch能捕獲系統異常。
GCC所實現的C++異常處理架構中,它的catch(…)文法,並不能捕獲系統異常。因此,這給C++中異常處理的良好運用打了大大的折扣;不同類型的系統異常等。所以Linux作業系統上的gcc編譯的程式中,它只能捕獲程式中,曾經被自己顯式地throw出來的異常,而對於系統異常,catch block是毫無辦法的。




解決:
///////////////
a.windows系統,調用.Using a Vectored Exception Handler..SEH機制來解決.比較麻煩.
b.linux系統,訊號來調用...比較麻煩.
c.自己多加判斷,Regex是個好東西..


異常的類型:
//////////////////
分為手動throw出來的異常..可以捕獲..
系統異常(如被0除,段錯誤,CPU異常等)




別的資料.
//////////////
ry{} catch(…){}
以前都是用try{} catch(…){}來捕獲C++中一些意想不到的異常, 今天看了Winhack的文章才知道,這種方法在VC中其實是靠不住的。例如下面的代碼:


try
{
BYTE* pch ;
pch = ( BYTE* )00001234 ;   //給予一個非法地址
*pch = 6 ; //對非法地址賦值,會造成Access Violation 異常
}
catch(...)
{
AfxMessageBox( "catched" ) ;
}
這段代碼在debug下沒有問題,異常會被捕獲,會彈出”catched”的訊息框。 但在Release方式下如果選擇了編譯器代碼最佳化選項,則VC編譯器會去搜尋try塊中的代碼, 如果沒有找到throw代碼, 他就會認為try catch結構是多餘的, 給最佳化掉。 這樣造成在Release模式下,上述代碼中的異常不能被捕獲,從而迫使程式彈出錯誤提示框退出。


那麼能否在release代碼最佳化狀態下捕獲這個異常呢, 答案是有的。 就是__try, __except結構, 上述代碼如果改成如下代碼異常即可捕獲。


__try




當然有, 就是仍然使用C++標準的try{}catch(..){}, 但在編譯命令列中加入 /EHa 的參數。這樣VC編譯器不會把try catch模組給最佳化掉了。


找到一篇比較好的英文文章談這個問






那麼C++標準中對於這種同一個程式有不同的運行結果有何解釋呢?這裡需要注意的是,window2000系統下catch(…)能捕獲住系統異常, 這完全是它自己的擴充。在C++標準中並沒有要求到這一點,它只規定catch(…)必須能捕獲程式中所有通過throw語句拋出的異常。因此上面的這個 程式在linux系統下的運行結果也完全是符合C++標準的。雖然大家也必須承認window2000系統下對C++異常處理模型的這種擴充確實是一個很 不錯的完善,極大得提高了程式的安全性。


以上代碼Debug版本運行不會彈對話方塊,因為"除零異常"了。而Release版本會彈,是因為變數a沒有用到,被編譯器最佳化掉了。若要使其不最佳化掉,把a使用printf函數列印出來。
可以去掉彙編實現的try,catch,看看編譯器會不會報錯!




最近看書時,看到異常處理中有try……except……
通常try -except是用來處理SEH異常的,而不是標準異常。具體參考下面的資料。
這兩個都講的很詳細~
c++ try-except statement




 




  在Windows系統中,使用VC2005編譯的debug版本代碼,try, catch能捕獲到被0除異常,在網上尋找下,說的是VC編譯器對try, catch作了擴充,使用了Windows特有的結構化異常處理(tructured Exception Handling,SEH)機制,據說要在release版本中使用SEH,要選擇編譯選項/Eha,這我沒有試過。
  摘抄一段話:SEH異常和C++異常有本質的區別, SEH是作業系統提供的異常處理技術, 在任何支援該作業系統的程式設計語言中, 都可以使用, 而C++異常處理只能在編寫C++代碼時使用。然而, 應當知道WINDOWS的VC++編譯器是使用作業系統結構化異常來實現C++異常的.  也就是說, C++的try塊在VC++下編譯時間, 會變成__try塊,  C++的catch塊會變成SEH的 __except塊: catch測試則變成SEH異常過濾器, catch中的代碼則變為__except中的代碼. 事實上, C++的throw塊, 在編譯的時候也會變成SEH的RaiseException函數調用, 由c++異常變為SEH異常.(http://blog.csdn.net/ydbcsdn/article/details/5271755)
  在linux下,使用g++去編譯時間,try, catch是無法捕獲被0除異常的,這我試過,不清楚是否有編譯選項支援,即使不支援,也是合理的,因為C++標準並不要求支援。
  若想代碼易於移植,或適用於多種系統,不要期望try,catch去捕獲系統異常,若明確知道只使用於windows系統除外,但要記得開啟編譯選項/Eha,否則達不到你的期望。
  
  
  
參考:
第21集 Windows系列作業系統平台中所提供的異常處理機制:希賽網軟體工程頻道.htm
(imp)C++-MinGW能支援VC的__try的文法嗎? - 德問 編程社交問答.htm
SEH異常,每個程式員都應當引起重視。 - CSDN論壇 - CSDN.NET.htm
imp...Using a Vectored Exception Handler (Windows).htmimp.
try?catch誤區_zhoujie_liang_新浪部落格.htm
imp....C語言的異常機制 setjump longjump函數【轉】 - 紅聯Linux門戶 - 中國領先的Linux技術網站 - 網站導航 - Linux通用技術 - Linux編程與核心.htm
imp,imp...C++-MinGW能支援VC的__try的文法嗎? - 德問 編程社交問答.htm


//  QT_CATCH(...)
       // catch(...)
     //   catch(...)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.