不要让继承自引用计数管理资源的对象在栈上实例
Posted bbqz007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不要让继承自引用计数管理资源的对象在栈上实例相关的知识,希望对你有一定的参考价值。
引用计数进行管理资源,我们最熟悉的就是智能指针。在c++11之前,我们的对象都从一个引用计数管理资源的类继承,这个类有一个引用计数器,两个配对的操作addref和delref,当delref将引用计数器减为0时,会自动调用delete。这种机制要求对象必须实例在堆上,也就是new创建。当决定继承一个对象时,你必须小心看一遍它的继承树,是否继承了这一种的类。
一旦你将使用引用计数管理资源的对象在栈上实例后,这个对象就有可能被栈和堆同时管理资源。首先在栈实例后,这个对象一定会在栈帧作用域内被管理资源,当离开栈帧时对象被释放。如果有一个函数很深层调用,或这个对象的某个接口函数将这个对象的指针送进了智能指针,这时就带来灾难了,这个对象又被堆管理上资源了。当这个意外的智能指针销毁时,这个栈上对象却用堆来管理资源了。或者这个意外的智能指针保留了一个野指针,栈对象已经离开作用域。
IceUtil::Thread就是一个例子。在主线程的栈上实例这些继承来的线程对象,然后开始这些线程,在主线程退出前停止这些线程,线程对象离开局部作用域对象被栈回收。但问题来了,IceUtil::Thread is a IceUtil::Shared,这个IceUtil::Shared就是一个引用计数管理资源的类。IceUtil::Thread::start(),这个接口在开始一个线程时,将线程对象以智能指针方式作为线程参数了,换句话说这个智能指针生命期与新线程相随。当主线程栈上的线程对象停止线程时,线程在退出时线程对象因为智能指针而被delete,灾难发生了。
boost::thread,IceUtil::Thread或其它框架库都有封装线程类,大家的设计的思想大致也都为重写run虚函数,start启动线程,stop停止线程。但是使用上细节不是全盘通用的。boost::thread可以在栈上实例,但IceUtil::Thread就小心了。
以上是关于不要让继承自引用计数管理资源的对象在栈上实例的主要内容,如果未能解决你的问题,请参考以下文章