boost库的强大,使用过的人都知道。在使用的过程中,多多少少容易出现些使用不对的地方。下面我就说一些我犯的错误,本人犯的错误呢,一般分分钟搞定,一般几天搞不定,最后找到问题才发现就是一个很小或者说 不应该犯的错误。
我共享出来这些问题,希望能帮到需要提醒的朋友们。
首先应该感谢如下:
1、这个群里的朋友对我的帮助,当然我也因为一个问题被T,被T是因为一个模板类怎么声明为友元类的时候,因为一句“你大爷”,然后就飞了~~
2、感谢神奇的~这个妹子朋友,我在上面群被T的时候,这个妹子加我给我帮助,一个很厉害的~,令我感到汗颜,再次感谢她给我的帮助。
为什么我的boost::shared_ptr指针的强引用计数明明大于1,为什么对象还是会被释放?
ok!
下面的代码图是我的一个指针管理器的一部分:
这个管理器的目的很简单,你给我指针,我给你存起来,然后给你返回弱指针,这样的目的在于,传递若指针避免对象被其他地方意外的释放。[题外话]当然,如果你想要释放这个若指针里的对象,也是可以的:
boost::weak_ptr::lock().get()
上面的代码纯属手打,如有错误,请参照boost的代码说明。上面的2个方法都是对象方法。
这样就能得到智能指针里的对象,你可以随意使用他,你就是把他释放了,智能指针也不知道。如果你得到上面的代码返回的指针如ptr,如果你使用boost::share_ptrok![题外话到此结束]。有可能你在图中发现了:
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
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();
}
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!
那么如何避免这个问题?
其他也不麻烦,把:
void Remove(T* p)
change to:
void Rempve(boost::weak_ptr ptr)
因为一开始当你添加一个指针的时候,你就已经得到了一个弱指针,所以这里传递一个弱指针应该是不太困难的。然后通过:
ptr.lock()
这句代码返回一个:
boost::shared_ptr
这个boost::shared_ptradd一个指针的代码:
__my_weak_ptr Add(T* p, boost::function 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);
}