使用boost::shared_ptr的教训

boost库的强大,使用过的人都知道。在使用的过程中,多多少少容易出现些使用不对的地方。下面我就说一些我犯的错误,本人犯的错误呢,一般分分钟搞定,一般几天搞不定,最后找到问题才发现就是一个很小或者说 不应该犯的错误。

我共享出来这些问题,希望能帮到需要提醒的朋友们。

首先应该感谢如下:

1、这个群里的朋友对我的帮助,当然我也因为一个问题被T,被T是因为一个模板类怎么声明为友元类的时候,因为一句“你大爷”,然后就飞了~~

2、感谢神奇的~这个妹子朋友,我在上面群被T的时候,这个妹子加我给我帮助,一个很厉害的~,令我感到汗颜,再次感谢她给我的帮助。


为什么我的boost::shared_ptr指针的强引用计数明明大于1,为什么对象还是会被释放?

ok!


下面的代码图是我的一个指针管理器的一部分:

使用boost::shared_ptr的教训_第1张图片


这个管理器的目的很简单,你给我指针,我给你存起来,然后给你返回弱指针,这样的目的在于,传递若指针避免对象被其他地方意外的释放。[题外话]当然,如果你想要释放这个若指针里的对象,也是可以的:

boost::weak_ptr::lock().get()

上面的代码纯属手打,如有错误,请参照boost的代码说明。上面的2个方法都是对象方法。

这样就能得到智能指针里的对象,你可以随意使用他,你就是把他释放了,智能指针也不知道。如果你得到上面的代码返回的指针如ptr,如果你使用boost::share_ptr(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(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(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 ptr)
因为一开始当你添加一个指针的时候,你就已经得到了一个弱指针,所以这里传递一个弱指针应该是不太困难的。然后通过:

ptr.lock()
这句代码返回一个:

boost::shared_ptr 
这个boost::shared_ptr对象,这个对象就和在set存储的 boost::shared_ptr对象是有连接的,共享所以他们的强引用计数也是使用的同一个,不像上面存在的问题,上面的问题的主要原因就是因为2个boost::shared_ptr指针对象是独立的,没有关联的,导致他们互相认不到自己的引用计数。

add一个指针的代码:

		__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);
		}








你可能感兴趣的:(boost,C++,c++,boost,shared_ptr,weak_ptr,指针)