shared_ptr是一个很好用的东西, 但是有些地方不注意也会带来很不必要的麻烦。
class test_ptr
{
};
typedef shared_ptr<test_ptr> TestPtr;
int main()
{
test_ptr* pTest = new test_ptr;
TestPtr sharePTest(pTest);
delete pTest;
return 0;
}
看看上面这段代码有没有问题? 这段代码什么也没做,可是在运行的时候程序去会崩溃。问题出在哪儿呢?
这是我在实际项目中遇到的问题, 当然实际的情况比这个要复杂。
这里的问题是pTest指针的内存被释放了两次, 所以程序崩溃了。
为什么?原因是这样的:
程序首先 new 了一个test_ptr对象,赋值给pTest指针, 然后又定义了一个智能指针对象sharePTest并用pTest初始化它。
这个时候实际有两个指针同时指向了同一个对象。程序的 delete pTest; 一句会释放这个对象。这看起来似乎没有问题,但当主函数返回后会发生什么呢?呵呵, 会析构sharePTest这个对象对不对, 可是这又有什么问题呢?
问题就在这里了,sharePTest是个智能指针,它析构的时候会把它所引用的指针的引用计数减1,然后检查引用计数是不是为0. 如果为0的话就去释放那个指针。
由于这个智能指针对象只被使用了一次,它的引用计数为1,析构的时候再递减就变为了, 所以这个时候它会去释放它所引用的指针。但是, 这个时候它所引用的指针
已经被释放过了,再次释放就会出问题了。
所以, 要么把内存释放全权委托给智能指针,像这样,TestPtr sharePTest(new test_ptr);就不用现调 delete 了。
要么就完全自己管理, 不要使用智能指针。
两者混用,实在太危险,有时候一些错误防不胜防啊。