2013-08
猜一下這個(gè)代碼的輸出
class Guard
{
public:
~Guard()
{
cout<<"guard destructing"<<endl;
}
};
class Bar
{
public:
~Bar()
{
cout<<"bar destructing"<<endl;
}
};
class Foo
{
public:
Bar b;
~Foo()
{
Guard g;
cout<<"foo destructing"<<endl;
}
};
void main(int argc,char **argv)
{
Foo b;
}
輸出
foo destructing
guard destructing
bar destructing
這個(gè)例子說(shuō)明:析構(gòu)函數(shù)體執(zhí)行完后,然后析構(gòu)棧變量,最后開(kāi)始析構(gòu)成員變量缺虐。
我們真實(shí)代碼中不是空蕩蕩的Guard類枉圃,功茴,真實(shí)代碼是這樣的:
LocalLicense::~LocalLicense()
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_CommonMutex);
......
LocalLicense::xxxxx()
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_CommonMutex);
......
用ACE_Guard來(lái)包裝mutex鎖,可以保證鎖的自動(dòng)釋放孽亲,這是我們常用的坎穿。這里試圖用一個(gè)鎖來(lái)同步析構(gòu)函數(shù)和成員方法,這樣就有問(wèn)題了返劲。結(jié)合上個(gè)例子:當(dāng)棧變量ACE_Guard被析構(gòu)后玲昧,鎖已經(jīng)釋放,然后才開(kāi)始析構(gòu)局部變量篮绿,此時(shí)成員函數(shù)可以獲得鎖并繼續(xù)執(zhí)行孵延,如果成員函數(shù)也訪問(wèn)同一個(gè)局部變量(此時(shí)可能正在被析構(gòu)),結(jié)果就是數(shù)據(jù)不一致搔耕,嚴(yán)重的可能導(dǎo)致coredump隙袁,掛死。
寫(xiě)了一個(gè)例子來(lái)模擬弃榨,見(jiàn)附件菩收,自己用main方法調(diào)用其中的guard_in_destructor,在linux和windows上發(fā)生coredump鲸睛,solaris上掛住
- 關(guān)于解決方法
參考網(wǎng)上的一篇文章《當(dāng)析構(gòu)函數(shù)遇到多線程──C++ 中線程安全的對(duì)象回調(diào)》娜饵。里邊推薦了使用shared_ptr,還有很多注意事項(xiàng)官辈。
shared_ptr這個(gè)不能完全套用到項(xiàng)目中箱舞,新開(kāi)發(fā)的可以參考這樣寫(xiě)遍坟,但我們實(shí)際解決方法需要因地制宜,比如用土辦法晴股,鎖然后加if(xx!=null)愿伴。否則實(shí)際要改動(dòng)的可能很多,風(fēng)險(xiǎn)更大电湘。