基类中 boost::shared_ptr 指向的对象永远不会被破坏
Posted
技术标签:
【中文标题】基类中 boost::shared_ptr 指向的对象永远不会被破坏【英文标题】:Object pointed by boost::shared_ptr in base class is never destroyed 【发布时间】:2015-02-27 20:08:13 【问题描述】:我对 boost shared_ptr 有一个奇怪的问题:
class A
A( )
: m_myObjectPtr( new MyObject( ) )
protected:
boost::shared_ptr<MyObject> m_myObjectPtr; // MyObject class is a simple class with a constructor and destructor
;
class B : A
B( )
void CleanMyObject( )
m_myObjectPtr.reset( );
;
class MyObject
MyObject( )
cout << "Constructed MyObject" << endl;
~MyObject( )
cout << "Destroyed MyObject" << endl;
;
我的问题是当我调用 B::CleanMyObject() 时从未调用 MyObject 的析构函数。 “Destroyed MyObject”永远不会被打印出来。
我在 ios 上使用 https://github.com/danoli3/ofxiOSBoost/blob/master/scripts/build-libc%2B%2B.sh 构建的 arm64 构建 boost 1_57 看到了这一点
有什么想法吗?
【问题讨论】:
Class
不是 C++ 中的关键字
共享指针是共享的。您是否(有意或无意地)将A
或B
对象复制到任何地方?发布创建和删除对象的完整示例会有所帮助。
这段代码显然不是您尝试的代码。有几个问题甚至无法编译类。
这是一个复杂项目的虚构示例,我无法在此处获得确切的代码。但根据我的检查,MyObjectPtr 从未在 A 类和 B 类之外被引用。
@ssk 对于此类问题,最好提供SSCCE
【参考方案1】:
显而易见的答案是您有多个 shared_ptr
s 引用单个对象,因此重置一个会减少引用计数但不会删除该对象。
即使shared_ptr
没有在A
和B
之外引用,也会发生这种情况。如果您分配 A
或 B
而不重载 operator=
或复制 A
或 B
(例如,按值传递,按值返回)而不重载复制构造函数,则会出现这种情况。
您可以通过多种方式进行调查。
您可以检查CleanMyObject
中的 boost::shared_ptr::use_count()
以查看它是否大于 1。
如果您不想共享和引用计数,可以将boost::shared_ptr
替换为std::unique_ptr
或boost::scoped_ptr
。
如果您想确保不会意外复制或分配A
或B
,可以从boost::noncopyable
派生A
。
【讨论】:
不错的建议,让我发布我的发现。谢谢。【参考方案2】:按照@Josh Kelley 的建议,使用 unique_ptr 为我解决了问题。
所以我将注意力转移到 boost::shared_ptr 以了解问题所在。事实证明,使用标志 BOOST_AC_USE_PTHREADS 和 BOOST_SP_USE_PTHREADS 为 iOS 构建提升是奇怪的最初原因。基于:
1) 安迪·温斯坦的回答:Boost threads: in IOS, thread_info object is being destructed before the thread finishes executing
2) 弱序CPU教程(http://preshing.com/20121019/this-is-why-they-call-it-a-weakly-ordered-cpu/)
很明显,我应该使用自旋锁,即 BOOST_SP_USE_SPINLOCK 标志来构建提升。
在我使用 BOOST_SP_USE_SPINLOCK 标志重建提升后,问题似乎得到了解决。
【讨论】:
您在添加 BOOST_SP_USE_SPINLOCK 时是否从脚本中删除了 BOOST_AC_USE_PTHREADS 和 BOOST_SP_USE_PTHREADS? @Danoli3 是的,我删除了 BOOST_AC_USE_PTHREADS 和 BOOST_SP_USE_PTHREADS。 太棒了,我已经继续审核了 Boost 脚本,并对所有 boost 库进行了此更改,因此没有其他人遇到此问题 ;)【参考方案3】:以下代码说明了一个工作示例。从 C++11 开始,它使用 std 命名空间中的 shared_ptr<T>
,但您可以替换为 boost::shared_ptr<T>
。
MyObject::~MyObject
在调用B::CleanMyObject
时被调用,就像您尝试做的那样。
#include <memory>
#include <iostream>
using namespace std;
class MyObject
public:
MyObject()
cout << "Constructed MyObject" << endl;
~MyObject()
cout << "Destroyed MyObject" << endl;
;
class A
protected:
A()
: m_myObjectPtr(new MyObject())
std::shared_ptr<MyObject> m_myObjectPtr; // MyObject class is a simple class with a constructor and destructor
;
class B : A
public:
B()
void CleanMyObject()
m_myObjectPtr.reset();
;
int main()
B b;
b.CleanMyObject();
【讨论】:
如果 boost 1_57 有 bug 怎么办? First Rule of Programming 总是你的错。 @NickStrupat 感谢您的回答和确认以上是关于基类中 boost::shared_ptr 指向的对象永远不会被破坏的主要内容,如果未能解决你的问题,请参考以下文章
通过取消引用 boost::shared_ptr 找不到派生类的方法