概念: “C++異常”就是 try{}catch(...){} “SEH異常”就是 __try{} __except(-1/0/1){} (關於這兩種異常,如有不了解的地方,網上有很多資料可以參考) 目前微軟所有的VC編譯器(從VC6到VC2010),都默認是打開對C++異常的編譯支持的(位於項目選項中的“代碼生成”->啟用C++異常:/EHsc,VC6是Enable Exception handling) (以下需要仔細閱讀) 在VC6中,對EXE工程是同時默認開啟“C++異常可以捕獲SEH異常”。在此條件下,用“C++異常”也可以捕獲向非法地址的讀寫等基本的Windows異常。 如:try{ int *a=0; *a=100; }catch(...){printf("excption!");},執行到*a=100時,會跳轉到catch塊,並執行printf。 但是,VC6建立的DLL或其他非EXE工程,如果是Release模式,並且編譯時,啟用了代碼自動優化,那么結果就變成了 只啟用了“C++異常”,即“C++異常無法捕獲SEH異常”。這樣的一個后果是,在DLL中,即使 像這樣用try{ int *a=0; *a=100; }catch(...){printf("excption!");}保護代碼, 當代碼執行到*a=100非法地址賦值語句時,catch(...)卻什么都捕獲不到,會直接造成程序崩潰。 除非明確使用“SEH異常”__try...__except(1)..,才能捕獲到這種Windows異常。 相應的解決辦法: 對於從VC7開始以及以后的VC++,在“代碼生成”->“啟用C++異常”處,均有第三個選項:“有效,但有SEH異常(/EHa)”, 這樣就是可以讓程序“使用C++異常也能夠捕獲到SEH異常”。 這樣無論是在EXE還是DLL中,try{}catch(...){}同樣可以捕獲Windows異常。 對於VC6的非EXE工程,有以下兩個方法,來用try..catch..捕獲Windows的SEH異常: 1、通過關閉編譯時的優化(禁用或者只使用Default級別,個人感覺是因為VC6的編譯器不是非常完善)。 2、通過在當前工程的編譯選項中,手工加上 /EHa 參數。這個編譯選項是沒有界面可以去設置的,只能手工添加。 這兩個方法選擇任何一個都可以。建議使用第二個方法。 另外要注意“C++異常”與“SEH異常”無法同時在同一個函數中混用。 更多 0
最好不要用C++異常去捕獲SEH異常。