基类中 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++ 中的关键字 共享指针是共享的。您是否(有意或无意地)将AB 对象复制到任何地方?发布创建和删除对象的完整示例会有所帮助。 这段代码显然不是您尝试的代码。有几个问题甚至无法编译类。 这是一个复杂项目的虚构示例,我无法在此处获得确切的代码。但根据我的检查,MyObjectPtr 从未在 A 类和 B 类之外被引用。 @ssk 对于​​此类问题,最好提供SSCCE 【参考方案1】:

显而易见的答案是您有多个 shared_ptrs 引用单个对象,因此重置一个会减少引用计数但不会删除该对象。

即使shared_ptr 没有在AB 之外引用,也会发生这种情况。如果您分配 AB 而不重载 operator= 或复制 AB(例如,按值传递,按值返回)而不重载复制构造函数,则会出现这种情况。

您可以通过多种方式进行调查。

您可以检查 CleanMyObject 中的 boost::shared_ptr::use_count() 以查看它是否大于 1。 如果您不想共享和引用计数,可以将boost::shared_ptr 替换为std::unique_ptrboost::scoped_ptr。 如果您想确保不会意外复制或分配AB,可以从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&lt;T&gt;,但您可以替换为 boost::shared_ptr&lt;T&gt;

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

通过取消引用 boost::shared_ptr 找不到派生类的方法

boost::shared_ptr与定制删除器

为啥基类指针指向基类中的纯虚方法,而不是派生类中的覆盖方法?

指向基类中成员函数的指针数组

sharePtr