boost庫的強大,使用過的人都知道。在使用的過程中,多多少少容易出現些使用不對的地方。下面我就說一些我犯的錯誤,本人犯的錯誤呢,一般分分鐘搞定,一般幾天搞不定,最後找到問題才發現就是一個很小或者說 不應該犯的錯誤。
我共享出來這些問題,希望能幫到需要提醒的朋友們。
首先應該感謝如下:
1、
這個群裡的朋友對我的幫助,當然我也因為一個問題被T,被T是因為一個模闆類怎麼聲明為友元類的時候,因為一句“你大爺”,然後就飛了~~
2、感謝
神奇的~這個妹子朋友,我在上面群被T的時候,這個妹子加我給我幫助,一個很厲害的~,令我感到汗顔,再次感謝她給我的幫助。
為什麼我的boost::shared_ptr指針的強引用計數明明大于1,為什麼對象還是會被釋放?
ok!
下面的代碼圖是我的一個指針管理器的一部分:
這個管理器的目的很簡單,你給我指針,我給你存起來,然後給你傳回弱指針,這樣的目的在于,傳遞若指針避免對象被其他地方意外的釋放。[題外話]當然,如果你想要釋放這個若指針裡的對象,也是可以的:
boost::weak_ptr<T>::lock().get()
上面的代碼純屬手打,如有錯誤,請參照boost的代碼說明。上面的2個方法都是對象方法。
這樣就能得到智能指針裡的對象,你可以随意使用他,你就是把他釋放了,智能指針也不知道。如果你得到上面的代碼傳回的指針如ptr,如果你使用boost::share_ptr<T>(ptr)來構造一個指針對象,那麼這第一個問題,就開始漸漸的浮出水面了。
ok![題外話到此結束]。有可能你在圖中發現了:
void Remove(T* p)
這個方法,這還是個私有方法,其實他沒什麼用,因為第一個問題就是他導緻的。全代碼為:
void Remove(T* p){
// 現在不在提供這個方法,
// __my_shared_ptr ptr(p);
// Remove(ptr);
}
一開始他為公開方法,因為我使用的集合:
typedef boost::unordered_set<__my_shared_ptr> __my_set;
集合裡存着的是 boost::share_ptr,是以我天真的以為,我構造一個boost::share_ptr<T>(ptr)傳給:
void Remove(__my_shared_ptr p){
Common::__scoped_lock lock(_PointerMgr_mutex);
__my_set::iterator find = _set.find(p);
if (find == _set.end()){
return;
}
__my_shared_ptr ptr = *find;
_set.erase(find);
//ptr.reset();
}
一開始我天真的以為構造一個 boost::share_ptr<T>(ptr)然後去調用這個Remove去從set裡移除這個對象就可以了,因為 我的想法是,使用相同的對象類型去find,應該比較容易,~~~想法就是如此的單純幼稚。但是!事實上證明,這麼做find的确是find到了一個有效的結果。ok!這裡沒有問題:
1、因為如果find的對象的引用計數為1,那麼erase from set 後智能指針就會删除對象。
2、因為如果find的對象的引用計數大于1, 那麼erase from set 後智能指針不會删除對象,這樣你可能需要reset,或者出于你的目的,還不想釋放這個對象。
當這裡執行完畢!,問題開始出現:
void Remove(T* p){
// 現在不在提供這個方法,
// __my_shared_ptr ptr(p);
// Remove(ptr);
}
當執行到"}"這個最後一個大括号的時候,如果上面的 1成立,則這個對象被釋放2次,如果你很幸運,那麼這裡會報記憶體錯誤。因為構造的ptr智能指針在這個方法裡結束了他的生命周期,是以他釋放的時候強引用-1,是以自然而然的再次delete。如果上面的 2成立,那麼你可能在想為什麼這個對象會被釋放~~~,苦思冥想,最後發現,還是因為這個臨時的智能指針對象造成的~
ok!
ok!
那麼如何避免這個問題?
其他也不麻煩,把:
void Remove(T* p)
change to:
void Rempve(boost::weak_ptr<T> ptr)
因為一開始當你添加一個指針的時候,你就已經得到了一個弱指針,是以這裡傳遞一個弱指針應該是不太困難的。然後通過:
ptr.lock()
這句代碼傳回一個:
boost::shared_ptr<T>
這個boost::shared_ptr<T>對象,這個對象就和在set存儲的 boost::shared_ptr<T>對象是有連接配接的,共享是以他們的強引用計數也是使用的同一個,不像上面存在的問題,上面的問題的主要原因就是因為2個boost::shared_ptr<T>指針對象是獨立的,沒有關聯的,導緻他們互相認不到自己的引用計數。
add一個指針的代碼:
__my_weak_ptr Add(T* p, boost::function<void(T*)> func = NULL){
__my_shared_ptr ptr(p, func);
return Add(ptr);
}
__my_weak_ptr Add(const __my_shared_ptr& p){
Common::__scoped_lock lock(_PointerMgr_mutex);
_set.insert(p);
return __my_weak_ptr(p);
}