使用boost::shared_ptr的教训
2015-01-08 22:49
204 查看
boost库的强大,使用过的人都知道。在使用的过程中,多多少少容易出现些使用不对的地方。下面我就说一些我犯的错误,本人犯的错误呢,一般分分钟搞定,一般几天搞不定,最后找到问题才发现就是一个很小或者说 不应该犯的错误。
我共享出来这些问题,希望能帮到需要提醒的朋友们。
首先应该感谢如下:
1、
这个群里的朋友对我的帮助,当然我也因为一个问题被T,被T是因为一个模板类怎么声明为友元类的时候,因为一句“你大爷”,然后就飞了~~
2、感谢
神奇的~这个妹子朋友,我在上面群被T的时候,这个妹子加我给我帮助,一个很厉害的~,令我感到汗颜,再次感谢她给我的帮助。
为什么我的boost::shared_ptr指针的强引用计数明明大于1,为什么对象还是会被释放?
ok!
下面的代码图是我的一个指针管理器的一部分:
这个管理器的目的很简单,你给我指针,我给你存起来,然后给你返回弱指针,这样的目的在于,传递若指针避免对象被其他地方意外的释放。[题外话]当然,如果你想要释放这个若指针里的对象,也是可以的:
上面的代码纯属手打,如有错误,请参照boost的代码说明。上面的2个方法都是对象方法。
这样就能得到智能指针里的对象,你可以随意使用他,你就是把他释放了,智能指针也不知道。如果你得到上面的代码返回的指针如ptr,如果你使用boost::share_ptr<T>(ptr)来构造一个指针对象,那么这第一个问题,就开始渐渐的浮出水面了。
ok![题外话到此结束]。有可能你在图中发现了:
一开始我天真的以为构造一个boost::share_ptr<T>(ptr)然后去调用这个Remove去从set里移除这个对象就可以了,因为 我的想法是,使用相同的对象类型去find,应该比较容易,~~~想法就是如此的单纯幼稚。但是!事实上证明,这么做find的确是find到了一个有效的结果。ok!这里没有问题:
1、因为如果find的对象的引用计数为1,那么erase from set 后智能指针就会删除对象。
2、因为如果find的对象的引用计数大于1, 那么erase from set 后智能指针不会删除对象,这样你可能需要reset,或者出于你的目的,还不想释放这个对象。
当这里执行完毕!,问题开始出现:
ok!
ok!
那么如何避免这个问题?
其他也不麻烦,把:
add一个指针的代码:
我共享出来这些问题,希望能帮到需要提醒的朋友们。
首先应该感谢如下:
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); }
相关文章推荐
- boost.shared_ptr源码整理和使用说明
- [C++] Boost智能指针——boost::shared_ptr(使用及原理分析)
- 在smart_ptr中处理引用计数时使用swap概念(boost::shared_ptr.hpp)
- [zz]使用boost::shared_ptr的注意条款
- boost shared_ptr的使用方法
- boost::shared_ptr 智能指针在项目中的使用
- Boost:使用shared_array和shared_ptr
- boost综合使用<function,bind,thread,mutex,condition_variable,shared_ptr>
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
- 小测试:boost之shared_ptr在容器类std::list中的使用
- boost::shared_ptr的使用方法
- boost::shared_ptr的使用方法
- boost::shared_ptr在类和容器中使用
- boost::shared_ptr的多线程使用陷阱
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
- boost::shared_ptr使用技巧
- 记录以下boost::shared_ptr的一个使用细节
- boost shared_ptr 使用注意点。
- 关于boost中shared_ptr使用方法的一些例子
- 使用 boost::shared_ptr 时,善用 make_shared 而非 new operator 去动态分配资源