異常處理方法
1. Windows SEH 與 C++ Exception
1) Windows SEH 結(jié)構(gòu)化異常
結(jié)構(gòu)化異常是Windows
操作系統(tǒng)提供的與語言無關(guān)的異常處理機(jī)制,
SHE使用Win32API中的RaiseException()函數(shù)來拋出異常,,在VC中使用關(guān)鍵字__try和關(guān)鍵字__except來捕獲,,并用宏
函數(shù)GetExceptionCode和GetExceptionInfo來獲取捕獲的異常由什么原因產(chǎn)生,和產(chǎn)生異常時(shí)環(huán)境狀態(tài),。__finally關(guān)
鍵字保證無論是否發(fā)生異常,,finally代碼段都會(huì)被執(zhí)行。
SHE使用示例代碼
int ECode;
__try
{
__try
{
RaiseException(1, // 拋出異常碼為1的SEH異常
0,
0, NULL); // 沒有參數(shù)
}
__finally
{
printf("2 "); // 不管是否有異常,,必定會(huì)執(zhí)行的代碼
}
}
__except (ECode=GetExceptionCode())
{
printf("發(fā)生異常,,Code=%d\n",ECode); // 捕獲異常后執(zhí)行的代碼 ;
}
輸出結(jié)果:
2發(fā)生異常,Code=1
2) C++Exception
C++標(biāo)準(zhǔn)也提供了一種異常處理機(jī)制,,通過使用try,catch,throw關(guān)鍵字來表達(dá),,在C++異常可以通過throw函數(shù)來拋出簡(jiǎn)單變量,,復(fù)雜變量與異常對(duì)象,,與Windows異常相比,異常對(duì)象可以給開發(fā)者提供更多的信息,。
try
{
//正常代碼
,。。,。
throw CExcetion();
,。。,。
}
catch (CException* e)
{
//處理異常代碼
}
3) SEH 到 C++異常的轉(zhuǎn)換
在同一個(gè)程序中,如果使用WIN32API它會(huì)拋出SHE,,使用C++庫函數(shù),它們又會(huì)拋出C++異常,,Win32API和C++函數(shù)混和使用時(shí)如果使用兩種異常捕獲機(jī)制時(shí),,使用起來會(huì)影響程序的可讀性,因此C++運(yùn)行庫提供了_set_se_translator函數(shù),,在SHE異常發(fā)生時(shí)通過回調(diào)方式來轉(zhuǎn)換SEH異常為C++異常,。在此提供一個(gè)轉(zhuǎn)換的宏來實(shí)現(xiàn)轉(zhuǎn)換,。
轉(zhuǎn)換宏的代碼:
#define INSTALL_SEHCONVERT() ExceptionConvert ecExceptionConvert
class SEHException
{
private:
unsigned int nSE;
public:
SEHException() {}
SEHException( unsigned int n ) : nSE( n ) {}
~SEHException() {}
unsigned int getSeNumber() { return nSE; }
};
class ExceptionConvert
{
public:
ExceptionConvert(){OldFanc = _set_se_translator(trans_func); }
~ExceptionConvert(){_set_se_translator(OldFanc); }
private:
static void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )
{
throw SEHException(u);
}
_se_translator_function OldFanc;
};
使用上面INSTALL_SEHCONVERT宏后就可以使用如下代碼來捕獲SHE異常了
INSTALL_SEHCONVERT();
Try
{
…
}
catch(SEHException &seh){
…
}
2. 同步異常與異步異常
1)
VC的C++ Exception
采用兩種模式捕獲異常:同步模式和異步模式。VC的工程的調(diào)試版本缺省使用異步模式,,工程的發(fā)布版本缺省使用同步模式,。在同步模式下,VC的編譯器假定代
碼中只有在顯示使用throw和調(diào)用函數(shù)的時(shí)候才會(huì)引發(fā)異常,,因此,,在同步模式下,VC編譯出的代碼比較小,,但在這種模式下,,try-catch對(duì)不能捕
獲內(nèi)存訪問異常與算術(shù)除零異常等。在異步模式下,,VC的編譯器為try塊內(nèi)的每一條語句生成異常捕獲代碼,,在這種情況下,他能夠捕獲全部的異常,,還能保證
棧上對(duì)象在解棧中正確釋放,。為了要在發(fā)行版本中也能夠捕獲全部異常就需要打開異步模式,但代價(jià)是程序編譯出代碼變大,,運(yùn)行速度變慢,。
2)編譯選項(xiàng):
同步模式的編譯選項(xiàng)為/EHs或者/GX(等同于/EHsc)
異步模式的編譯選項(xiàng)為/EHa
3. 多線程下的異常捕獲
在創(chuàng)建線程并運(yùn)行線程的函數(shù)中把創(chuàng)建線程的代碼放在try塊中并不會(huì)捕獲到線程函數(shù)中發(fā)生的異常,線程函數(shù)中發(fā)生的異常只能在線程函數(shù)中捕獲,。并且每一個(gè)線程都需要自己的SHE轉(zhuǎn)換宏,。轉(zhuǎn)換宏可以放在線程函數(shù)的開始部分
4.參考MSDN庫