青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

alex

alex

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  7 隨筆 :: 6 文章 :: 7 評論 :: 0 Trackbacks

今天來講講怎么編寫異常安全的代碼。
程序運行過程中,往往需要對一些流程加入異常處理,來提高程序的robust.比如
通過try catch來捕捉異常
try
{
??? pMemory = new char[MAX_BUF_SIZE];
}
catch(std::bad_alloc& e)
{
??? //error handling,er:do something resource free
}
但在程序代碼段中出現大量的try catch,不僅從美觀,效率和程序輸寫上都是不怎么好。
而另外一種對于異常的處理方法是依賴于c++的ctor/dctor的匹配來做的,就是所謂的
RAII,這個很容易讓人聯想到std::auto_ptr
std::auto_ptr<int> tmp(new int);
通過new分配的對象會在tmp生命結束后,釋放相關的資源,通過這種方式,就能保證在程序異常,或退出時,已分配的對象能正確自動的釋放擁有的資源,而在對象聲明周期內,可以保證資源的有效性。
這種方式就是今天blog要寫的主要內容,我們可以看到std::auto_ptr作用范圍很小,只能對從堆上分配的對象進行管理,假如對文件打開句柄實行RAII,你也許會認為再寫個不就是了,但這樣只會造成源代碼里充滿了這些資源管理的類,這導致了一個嚴重的問題,好的結構在繁瑣的流暢前面變的難堪。
那怎么樣對這個進行泛化,從而能對比如從簡單的指針釋放,文件句柄維護,甚至相關的成員函數。我們來看下loki::socpeguard是怎么實現的:
先看下基本的用法
(1)? FILE* hFileOpen = fopen(....);
(2)? LOKI_ON_BLOCK_EXIT(flose,hFileOpen);
line2會在出LOKI_ON_BLOCK_EXIT域或程序異常結束時被調用,下面是對類成員的調用
void CTestObject::Create
{
??? LOKI_ON_BLOCK_EXIT_OBJ(*this,FressResouce);
??? ...
}
同上面差不多,會在這個函數結束后或異常結束后調用類成員的FreeResource.在正常流程結束后,可以通過調用Dismiss來防止對FreeResouce的調用,即類似數據庫操作的commit操作。下面來分析下LOKI的實現:
從上面可以看到,RAII的是:
1:構造函數對資源的獲取
2:稀構函數對資源的釋放
先來看下LoKi對上面那2個宏的定義
#define LOKI_ON_BLOCK_EXIT????? Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeGuard

#define LOKI_ON_BLOCK_EXIT_OBJ? Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeObjGuard
上面的Loki::ScopeGuard是一個基類的別名
typedef const ScopeGuardImplBase& ScopeGuard;
而LOKI_ANONYMOUS_VARIABLE(scopeGuard)用來我們產生唯一的名字,有時假如需要調用Dismiss的話,則需要自己去實現宏定義的內容,這樣才能通過對象訪問。Loki::MakeGuard或Loki::MakeObjGuard是用來產生對象的實際類型的,下面是一個
Loki::MakeGuard的例子:
template <typename F, typename P1>
inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
{
??? return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
}
可以看到ScopeGuardImpl1<F, P1>是要產生的具體類型,MakeGuard通過函數參數的數目來重載的,而MakeGuard此處的作用是要睡死了...-_-'',作用是利用函數自動推導出參數的類型,這樣就免去了指定ScopeGuardImpl1的類型的麻煩,而
ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
簡單的返回對象的一個臨時變量,并assign給一個上面的一個scopeguard的實例,這里依賴一個C++的特性,臨時變量的聲命周期和通過他初始化的引用類型的聲明周期是一致的。

從上面可以看到Loki定義了一個ScopeGuardImplBase的基礎類。這個類定義了一個基本的方法Dismiss,以及相關的狀態。下面是loki中這個類的定義
class ScopeGuardImplBase
{
??? ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
?protected:
??? ~ScopeGuardImplBase()
??? {}
??? ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
??????? : dismissed_(other.dismissed_)
??? {
??????? other.Dismiss();
??? }
??? template <typename J>
??? static void SafeExecute(J& j) throw()
??? {
??????? if (!j.dismissed_)
?????????? try
?????????? {
????????????? j.Execute();
?????????? }
?????????? catch(...)
?????????? {}
???? }
???????
???? mutable bool dismissed_;
public:
???? ScopeGuardImplBase() throw() : dismissed_(false)
???? {}
???? void Dismiss() const throw()
???? {
???????? dismissed_ = true;
????? }
};
可以看到類里面定義了上面所說的一些屬性,其中SafeExecute用來提供子類同一的資源釋放方法,并調用子類的方法來具體操作,因為相關的函數,變量都保存在具體的子類,可以看到這個函數使用了try catch,這里加這個的目的是,因為資源釋放要在子類的稀構里被觸發,而調用具體的方法是外面傳進來的,所以無法保證一定是異常安全的,而假如在稀構里面異常的話,會導致程序的行為無法定義。
下面具體來看下一個子類的實現:
template <typename F, typename P1>
class ScopeGuardImpl1 : public ScopeGuardImplBase
{
public:
??? static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
??? {
??????? return ScopeGuardImpl1<F, P1>(fun, p1);
??? }
??? ~ScopeGuardImpl1() throw()
??? {
??????? SafeExecute(*this);
??? }
??? void Execute()
??? {
??????? fun_(p1_);
??? }
protected:
??? ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
??? {}
??? F fun_;
??? const P1 p1_;
};
在LoKi里面可以看到很多類似ScopeGuardImpl1的定義,比如ScopeGuardImpl0,
ScopeGuardImpl2,可以發現最后面的數字表示具體參數的數目。
可以看到上面所說的MakeGuard的定義,以及對基類方法的調用,可以看到構造函數接收的類型,一個函數對象,和一些參數對象,并保存,對于成員函數的scopeguard,LoKi定義了1些相似的類,主要是增加了對象的引用,還有就是函數的調用方式上。
上面可以看到參數是通過值的方式來保存的而不是通過引用。而且是const屬性的,下面是相關的分析。
1:通過傳值的方式,從而避免了異常拋出時,可能引用的對象被稀構
2:加const屬性,從而保證了在func需要參數是reference時而保存的參數確是非const時產生相應的編譯錯誤,因為對reference傳人const non-reference形式是錯誤的。
而對于1的方式,存在的一種問題是假如操作的fun需要傳入引用,那傳進去的值就無法在釋放的函數中被改變,而2是對這種的一種類似契約似的編程,Loki 提供的方法是通過一個中間對象來保存操作參數的引用,并賦予這個對象自動轉換功能。下面是這個類的定義:
template <class T>
class RefToValue
{??
public:
??? RefToValue(T& ref) : ref_(ref)
??? {}
??? RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
??? {}
??? operator T& () const
??? {
??????? return ref_;
??? }
private:
??? // Disable - not implemented
??? RefToValue();
??? RefToValue& operator=(const RefToValue&);
???????
??? T& ref_;
};
可以很清楚的看到類的實現,下面是一個工具類
template <class T>
inline RefToValue<T> ByRef(T& t)
{
???? return RefToValue<T>(t);
}
下面給個具體的例子,假如
template<typename _Ty>
void SAFEDELETE(_Ty*& ptr)
{
?? if (NULL != ptr)
????? delete ptr;
?? ptr = NULL;
}

char* ptr = new char;
?
{
??? LOKI_ON_BLOCK_EXIT(SAFEDELETE<char>,Loki::ByRef(ptr));
}
?
if (NULL == ptr)
? std::cout << "NULL" << std::endl;
基本上就這么多了,sleep去了
??????????????????????????????????????????????????? alex_yuu

posted on 2007-02-11 15:55 agerlis 閱讀(1409) 評論(3)  編輯 收藏 引用

評論

# re: 編寫異常安全的代碼(loki::scopeguard) 2007-02-11 15:56 agerlis
請問,怎么設置背景色?  回復  更多評論
  

# re: 編寫異常安全的代碼(loki::scopeguard) 2007-02-12 16:13 mc
不錯,把Loki::ScopeGuard介紹的比較透徹了:)  回復  更多評論
  

# re: 編寫異常安全的代碼(loki::scopeguard) 2007-05-28 16:40 candy
看到這些代碼我就暈了,厲害啊,我比較討厭編程。。嘿嘿,我是龔芳萍。  回復  更多評論
  


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            91久久精品美女高潮| 在线观看日韩专区| 久久成人免费视频| 亚洲欧美在线免费| 欧美一级理论片| 久久久久成人精品| 欧美r片在线| 欧美理论视频| 国产精品网曝门| 国模精品一区二区三区色天香| 国产亚洲欧美在线| 亚洲国产日韩综合一区| 亚洲美女中文字幕| 亚洲欧美日韩中文播放| 久久久久久久综合日本| 六月天综合网| 欧美一区二区三区免费观看视频| 亚洲精品乱码久久久久久日本蜜臀 | 国产欧美精品一区aⅴ影院| 日韩午夜免费| 欧美丰满高潮xxxx喷水动漫| 久久久水蜜桃| 亚洲欧洲精品一区二区三区| 久久综合伊人77777蜜臀| 亚洲高清免费在线| 亚洲桃花岛网站| 欧美大片免费久久精品三p | 一区二区三区四区蜜桃| 久久久久久久久伊人| 日韩小视频在线观看| 久久久91精品国产一区二区三区| 欧美日韩在线免费| 亚洲二区在线视频| 久久精品夜色噜噜亚洲a∨| 亚洲人体影院| 亚洲欧美日韩天堂一区二区| 亚洲国产另类 国产精品国产免费| 国产精品热久久久久夜色精品三区| 欧美成人四级电影| 国产中文一区二区| 欧美激情二区三区| 欧美性片在线观看| 亚洲视频欧美在线| 欧美日韩另类字幕中文| 亚洲韩国精品一区| 久久人人爽人人爽爽久久| 亚洲视频在线一区| 欧美日韩免费高清一区色橹橹| 欧美在线视频一区二区| 亚洲激情欧美| 性欧美大战久久久久久久久| 欧美久久影院| 亚洲国产高清在线| 久久人人97超碰精品888| 一区二区国产在线观看| 国产日产欧产精品推荐色 | 欧美高清在线| 欧美一级久久久| 免费欧美日韩| 香蕉免费一区二区三区在线观看| 久久久精品五月天| 在线综合亚洲| 久久尤物视频| 欧美在线免费观看视频| 欧美精品一区二区蜜臀亚洲| 久久人人97超碰国产公开结果| 欧美性色视频在线| 亚洲欧洲日本专区| 狠狠干综合网| 午夜精品久久久久久久久久久久| 一本久久a久久免费精品不卡| 先锋影音久久久| 亚洲社区在线观看| 欧美国产日韩一二三区| 久久久噜噜噜久久人人看| 欧美日韩在线不卡| 亚洲精品欧美在线| 亚洲福利视频一区二区| 性欧美大战久久久久久久免费观看| 99综合精品| 免费观看成人鲁鲁鲁鲁鲁视频| 久久久久久自在自线| 国产精品毛片在线看| 亚洲国产你懂的| 又紧又大又爽精品一区二区| 中日韩美女免费视频网站在线观看| 在线电影国产精品| 亚久久调教视频| 午夜精品亚洲一区二区三区嫩草| 欧美裸体一区二区三区| 亚洲福利一区| 亚洲高清av| 一本色道精品久久一区二区三区| 久久国产精品99国产精| 亚洲精品久久久久久久久久久久久 | 亚洲美女中文字幕| 韩国av一区二区三区四区| 亚洲影院色在线观看免费| 亚洲天堂av高清| 国产精品vvv| 一本色道久久综合亚洲精品不| 欧美日韩免费高清| 99国产一区| 亚洲一区欧美激情| 国产精品少妇自拍| 欧美一级二级三级蜜桃| 久久久噜噜噜久久人人看| 尤物yw午夜国产精品视频明星| 久久婷婷色综合| 亚洲人妖在线| 午夜精品久久一牛影视| 国产欧美视频一区二区| 欧美在线网址| 欧美成人精品不卡视频在线观看 | 在线精品视频免费观看| 久久综合狠狠综合久久综合88| 久久综合一区二区三区| 亚洲国产精品福利| 欧美精品一区二区精品网| 99国产精品久久久久老师| 欧美在线观看一区二区三区| 国产一区二区三区av电影| 久久久久国产成人精品亚洲午夜| 欧美黄网免费在线观看| 一区二区三区国产在线| 欧美午夜精彩| 久久精品国产精品亚洲综合| 欧美成人免费播放| 亚洲影院色无极综合| 韩国av一区二区三区| 亚洲作爱视频| 久久综合伊人77777尤物| 亚洲精品视频免费在线观看| 久久av资源网站| 欧美日韩亚洲一区三区| 欧美激情小视频| 亚洲国产另类 国产精品国产免费| 欧美一区1区三区3区公司| 欧美亚洲一区| 国产精品区一区二区三区| 欧美一区影院| 亚洲欧美精品| 99精品久久免费看蜜臀剧情介绍| 国产精品日本| 免费看精品久久片| 亚洲大黄网站| 久久精品视频免费播放| 亚洲精一区二区三区| 国产午夜精品美女视频明星a级| 蜜桃久久av一区| 午夜久久久久久| 亚洲视频欧美在线| 亚洲三级影片| 欧美国产一区视频在线观看 | 一本久久综合亚洲鲁鲁五月天| 久久伊人亚洲| 午夜亚洲福利在线老司机| 亚洲精品一区二| 在线免费观看日韩欧美| 国产免费一区二区三区香蕉精| 欧美精品一区在线播放| 久久精品亚洲热| 亚洲欧美制服另类日韩| 亚洲性感美女99在线| 亚洲精品四区| 亚洲九九九在线观看| 亚洲高清免费视频| 欧美va亚洲va国产综合| 久久久久久久久久码影片| 午夜精品久久久久99热蜜桃导演| 一区二区三区日韩| 妖精成人www高清在线观看| 在线观看一区| 在线电影国产精品| 韩国女主播一区二区三区| 国产日韩欧美91| 国产麻豆91精品| 国产欧美精品日韩| 国产欧亚日韩视频| 国产一区二区三区四区五区美女| 国产精品毛片在线看| 亚洲三级影院| 午夜激情综合网| 亚洲人成艺术| 国产亚洲一区二区三区| 欧美乱妇高清无乱码| 久久精品一区二区三区不卡牛牛 | 一区二区三区|亚洲午夜| 亚洲青涩在线| 一区二区三区精品视频| 亚洲视屏在线播放| 亚洲欧美网站| 久久久久综合一区二区三区| 久久综合久久综合这里只有精品| 麻豆精品在线视频| 欧美日韩国产精品一区| 国产精品video| 国产一区在线播放| 亚洲第一伊人| 亚洲视频视频在线|