【问题标题】:Object pointed by boost::shared_ptr in base class is never destroyed基类中 boost::shared_ptr 指向的对象永远不会被破坏
【发布时间】: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

标签: c++ ios boost shared-ptr arm64


【解决方案1】:

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

即使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&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 感谢您的回答和确认
猜你喜欢
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多