基 class 中 boost::shared_ptr 指向的对象永远不会被销毁

Object pointed by boost::shared_ptr in base class is never destroyed

我对 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

有什么想法吗?

以下代码说明了一个工作示例。它使用从 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();
}

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

即使未在 AB 之外引用 shared_ptr,也会发生这种情况。如果您分配 AB 而不重载 operator= 或复制 AB(例如,按值传递,return 按值传递)而没有重载复制构造函数,那么就会产生这样的结果。

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

  • 您可以检查 CleanMyObject 中的 boost::shared_ptr::use_count() 是否大于 1。
  • 如果您不想共享和引用计数,您可以将 boost::shared_ptr 替换为 std::unique_ptrboost::scoped_ptr
  • 如果您想确保没有意外复制或分配 AB,您可以从 boost::noncopyable.[=40= 派生 A ]

按照@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 后,问题似乎得到了解决。