1. 程式人生 > >關於C++異常處理和win32結構化異常處理

關於C++異常處理和win32結構化異常處理

2011-09-26

周海漢 abloz.com 2011-09-26

C++中經常會用到try…catch()結構來進行異常處理。但windows平臺VS2005之後,預設的配置,try catch是抓不到硬體異常的,如訪問非法記憶體和除以0。而vs2005之前的try catch能抓住硬體異常,可是因為不能正確處理,還是會導致程式錯誤。

那麼windows平臺只使用結構化異常處理呢?全部用__try,__except(). 這樣還是不行,因為C++的異常__try又不能抓取。那麼二者共用呢?對不起,仍然不行,因為這兩種異常處理機制不一樣,不能公用。 C++的try catch是會做迴繞的,會跟蹤物件的建立和釋放。而win的是__try是對硬體中斷異常的處理,僅適用於windows平臺。

二者共存,如下的簡單程式碼,編譯會提示錯誤:error C2712: 無法在要求物件展開的函式中使用 __try

void divbyzero( int j)
{
	std::string strTest;         // 錯誤!結構化異常無法解析C++ 物件
	__try
	{
		int i = 1;
		i=1/j;
	}
	__except(cout<<"exception filter in divbyzero()n",0)
	{  
		//0=EXCEPTION_CONTINUE_SEARCH 會傳遞到外層except,1=EXCEPTION_EXECUTE_HANDLER 終結,-1=EXCEPTION_CONTINUE_EXECUTION在excpt.h定義
		cout<<"exception error in divbyzero()" <<endl;
	}
}

關於異常的處理,windows下的編譯器版本不同,處理方式還不一樣。vs2005(vc8)以前的編譯器如vc6,vc7都預設能抓獲SEH異常。而vs2005以後的,預設是不抓獲seh異常的。 對如下的測試程式碼:

// testtry.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <exception>
#include <iostream>
using namespace std;

void crashmem(void)
{
	int *p = NULL;

	try
	{
		*p = 1;

		cout<<"process in crashmem()"<<endl;
	}
	catch(...)
	{
		cout << "catch exception in crashmem()" << endl;
	}

	cout<<"after catch in crashmem()"<<endl;

}
void divbyzero( int j)
{
	//std::string strTest;         // 錯誤!結構化異常無法解析C++ 物件
	__try
	{
		int i = 1;
		i=1/j;
	}
	__except(cout<<"exception filter in divbyzero()n",1)
	{
		//0=EXCEPTION_CONTINUE_SEARCH 會傳遞到外層except,1=EXCEPTION_EXECUTE_HANDLER 終結,-1=EXCEPTION_CONTINUE_EXECUTION在excpt.h定義
		cout<<"exception error in divbyzero()" <<endl;
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int i = 1;
	int j = 0;

	try
	{
		crashmem();
		divbyzero(0);

		cout << "main() process" << endl;
	}
	catch(...)
	{
		cout << "catched exception in main()" << endl;
	}

	cout << "good in main()" << endl;

	getchar();
	return 0;
}

預設配置, 在VS2003中測試,列印結果:

catch exception in crashmem()
 after catch in crashmem()
 exception filter in divbyzero()
 exception error in divbyzero()
 main() process
 good in main()

而在vs2010中直接崩潰。 但如果在vs2010中設定可以抓取SEH:專案>屬性>c/c++>程式碼生成 啟用C++異常,選/EHa,有seh異常。則列印

catch exception in crashmem()
 after catch in crashmem()
 main() process
 good in main()




如果將1改為0 EXCEPTION_CONTINUE_SEARCH
 則vs2003列印:
 catch exception in crashmem()
 after catch in crashmem()
 exception filter in divbyzero()
 catched exception in main()
 good in main()




vs2010列印
 catch exception in crashmem()
 after catch in crashmem()
 main() process
 good in main()
 <strong></strong>

參考:

http://blog.csdn.net/kongbu0622/article/details/4233946

http://thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源