代码之家  ›  专栏  ›  技术社区  ›  ssk

基类中boost::shared_ptr指向的对象永远不会被破坏

  •  0
  • ssk  · 技术社区  · 10 年前

    我对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上看到了这一点,arm64版本为boost 1_57,使用 https://github.com/danoli3/ofxiOSBoost/blob/master/scripts/build-libc%2B%2B.sh

    有什么想法吗?

    3 回复  |  直到 10 年前
        1
  •  3
  •   Josh Kelley    10 年前

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

    即使 共享ptr 未在外部引用 A B 。如果您分配 A. B 不超载 operator= 或复制 A. B (例如,按值传递,按值返回),而不重载复制构造函数,则会导致此结果。

    有几种方法可以进行调查。

    • 你可以检查一下 boost::shared_ptr::use_count() 在您的 CleanMyObject 看看它是否大于1。
    • 如果您不希望共享和引用计数,可以替换 boost::shared_ptr 具有 std::unique_ptr boost::scoped_ptr .
    • 如果您想确保您没有意外复制或分配 A. B ,可以导出 A. 从…起 boost::noncopyable .
        2
  •  3
  •   Community CDub    8 年前

    按照@JoshKelley的建议,使用unique_ptr为我解决了问题。

    所以我把注意力转移到boost::shared_ptr上,以了解问题所在。事实证明,使用标志boost_AC_USE_PTHREADS和boost_SP_USE_PTHEREADS为iOS构建boost是出现这种奇怪现象的最初原因。基于:

    1) Andy Weinstein的回答: 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/ )

    很明显,我应该使用Spin Lock,即BOOST_SP_USE_SPINLOCK标志来构建BOOST。

    在我用boost_SP_USE_SPINLOCK标志重建了boost之后,问题似乎得到了解决。

        3
  •  2
  •   Nick Strupat    10 年前

    下面的代码说明了一个工作示例。它使用 shared_ptr<T> 从C++11中开始的std命名空间,但可以替换 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();
    }