内容摘要:一些C++ 书上经常告诫程序员:要养成好的习惯,new 与 delete 要成对出现,时刻记住将内存释放回系统。但是,事情只是这么简单吗?
当到了这里时,我便以为大功告成,忍不住摸拳搽掌,很想试一试。结果发现对于一般的情况,效果确实不错,达到了垃圾回收的效果。如下面的应用:
auto_ptr p1=new test;
auto_ptrp2 = p1;
auto_ptrp3 = new test;
但是,很快地,我在测试前面提到的回环时,就发现了问题,我是这样测试的:
class test
{
auto_ptr p;
};
auto_ptr p1=new test;
auto_ptrp2 =new test;
p1->p=p2;
p2->p=p1;
当程序执行离开作用域后,这两块内存并没有象我想象的那样被释放,而是一直保留在堆中,直到程序结束。我仔细分析造成这种现象的原因,发现了一个非常有趣的问题,我把它称之为互锁现象。
上面p1 所拥有的指针被两个灵巧指针所拥有,除p1外,还有p2所拥有的 test 类中的灵巧指针p,p2亦然。也就是说,这两块内存的指针的引用记数都为 2 。当程序执行离开作用域后,p1,p2被析构,使它们的引用记数都为1,此后再没有灵巧指针被析构而使它们的引用记数变为 0 ,因此它们将长期保留在堆中。这就象两个被锁住的箱子,其中每个箱子中都装着对方的钥匙,但却无法把彼此打开,这就是互锁现象。
可是如何解决呢?看来必须对它进行改进。同时,我也发现上面的方法不支持多线程。所以,我们改进后的方法不仅要解决互锁现象,而且还要支持多线程。下面是我改进后的方法:
首先是如何发现这种互锁现象。我们知道,互锁现象产生的根源在于拥有堆中内存的灵巧指针本身也存在于已分配的堆内存中,那么,如何发现灵巧指针是存在于堆中还是栈中就成了问题的关键。由此,我引入了一个新的类 CPtr,由它来管理用 new 分配的指针,而 CPtrManager 专门用来管理 CPtr。如下所示:
责编:豆豆技术应用