C++華麗的exception handling(異常處理)背后隱藏的陰暗面及其處理方法
作者: 來源: 發(fā)布時(shí)間:2012-2-1 8:32:23 點(diǎn)擊:
看看下面這個(gè)簡(jiǎn)單例子:
#include <memory>
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass(){};
~BaseClass()
{
throw runtime_error("example runtime error.");
};
};
int main(int *argc , char **argv)
{
BaseClass *pBase = new BaseClass;
delete pBase;
return 0;
}
在VS2008下調(diào)用teminate時(shí)候還會(huì)調(diào)用abort,這個(gè)程序會(huì)非正常結(jié)束,如果在main函數(shù)中試圖這樣做:
int main(int *argc , char **argv)
{
BaseClass *pBase = new BaseClass;
try
{
delete pBase;
}
catch(runtime_error &err)
{
cout<<err.what()<<endl;
}
return 0;
}
結(jié)果會(huì)跟上面一樣(非正常結(jié)束),因?yàn)閐elete是不會(huì)將任何異常傳遞到其外面的;一種比較折中的解決方法是,當(dāng)destructor中存在異常拋出時(shí),在destructor最后添加一個(gè)能捕獲所有異常的catch處理塊,catch處理塊又什么工作都不做,如下:
~BaseClass()
{
try
{
throw runtime_error("error in destructor");
}
catch(...)
{
}
};
看起來是一種很壞很無奈的辦法,但正如Scott Meyers在《effective c++》中所說:
“一般而言,將異常吞掉是個(gè)壞主意,因?yàn)樗鼔褐屏?quot;某些動(dòng)作失敗"的重要信息!然而有時(shí)候吞下異常也比負(fù)擔(dān)"草率結(jié)束程序"或"不明確行為帶來的風(fēng)險(xiǎn)好”。
后記
對(duì)于很多exception handling的概念性細(xì)節(jié)(比如何時(shí)使用引用類型的異常捕捉、異常捕獲層次的類型轉(zhuǎn)換等等)我沒做任何闡述,可以去看看《C++ PRIMER》的第十七章,有著很想盡的講解。。。 對(duì)于MS編譯器對(duì)異常規(guī)范的不支持,我很難理解,因?yàn)镚++編譯器確實(shí)是支持的。之前在討論C++的object布局時(shí)(點(diǎn)擊這里)也曾感嘆MS的編譯器在優(yōu)化方面沒G++走得快,對(duì)于這些,或許是我運(yùn)氣不好,老是碰到MS不如G++的地方,也或許是我現(xiàn)在幾乎不用G++編譯器的而體會(huì)不到其不如MS編譯器的地方的緣故吧。。。exception handling的確能為提高代碼質(zhì)量的改善作出或多說少的貢獻(xiàn),但華麗麗的外表下,因?yàn)橛貌缓盟鴮?dǎo)致的程序的很多不明確(如teminate當(dāng)前程序)和不正常(如資源泄露)行為也是令人比較頭大的地方。貌似只有多熟用有技巧性的用是唯一能解決所有問題的方法了。。
#include <memory>
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass(){};
~BaseClass()
{
throw runtime_error("example runtime error.");
};
};
int main(int *argc , char **argv)
{
BaseClass *pBase = new BaseClass;
delete pBase;
return 0;
}
在VS2008下調(diào)用teminate時(shí)候還會(huì)調(diào)用abort,這個(gè)程序會(huì)非正常結(jié)束,如果在main函數(shù)中試圖這樣做:
int main(int *argc , char **argv)
{
BaseClass *pBase = new BaseClass;
try
{
delete pBase;
}
catch(runtime_error &err)
{
cout<<err.what()<<endl;
}
return 0;
}
結(jié)果會(huì)跟上面一樣(非正常結(jié)束),因?yàn)閐elete是不會(huì)將任何異常傳遞到其外面的;一種比較折中的解決方法是,當(dāng)destructor中存在異常拋出時(shí),在destructor最后添加一個(gè)能捕獲所有異常的catch處理塊,catch處理塊又什么工作都不做,如下:
~BaseClass()
{
try
{
throw runtime_error("error in destructor");
}
catch(...)
{
}
};
看起來是一種很壞很無奈的辦法,但正如Scott Meyers在《effective c++》中所說:
“一般而言,將異常吞掉是個(gè)壞主意,因?yàn)樗鼔褐屏?quot;某些動(dòng)作失敗"的重要信息!然而有時(shí)候吞下異常也比負(fù)擔(dān)"草率結(jié)束程序"或"不明確行為帶來的風(fēng)險(xiǎn)好”。
后記
對(duì)于很多exception handling的概念性細(xì)節(jié)(比如何時(shí)使用引用類型的異常捕捉、異常捕獲層次的類型轉(zhuǎn)換等等)我沒做任何闡述,可以去看看《C++ PRIMER》的第十七章,有著很想盡的講解。。。 對(duì)于MS編譯器對(duì)異常規(guī)范的不支持,我很難理解,因?yàn)镚++編譯器確實(shí)是支持的。之前在討論C++的object布局時(shí)(點(diǎn)擊這里)也曾感嘆MS的編譯器在優(yōu)化方面沒G++走得快,對(duì)于這些,或許是我運(yùn)氣不好,老是碰到MS不如G++的地方,也或許是我現(xiàn)在幾乎不用G++編譯器的而體會(huì)不到其不如MS編譯器的地方的緣故吧。。。exception handling的確能為提高代碼質(zhì)量的改善作出或多說少的貢獻(xiàn),但華麗麗的外表下,因?yàn)橛貌缓盟鴮?dǎo)致的程序的很多不明確(如teminate當(dāng)前程序)和不正常(如資源泄露)行為也是令人比較頭大的地方。貌似只有多熟用有技巧性的用是唯一能解決所有問題的方法了。。
[收藏此文章]