包含指向自身的智能指针的对象,该指针在对象超出范围之前未重置

object containing smart pointer to itself that isn't reset before object goes out of scope

本文关键字:指针 对象 范围 智能 包含指      更新时间:2023-10-16

遇到了这个错误,其中类包含指向自身的指针 - 并且它指向同一实例。这是包含该问题的最小代码片段...

class Node
{
public:
    Node()
    {
        std::cout << "constructor" << std::endl;
    }
    ~Node()
    {
        std::cout << "destructor" << std::endl;
    }
    void storeChild(boost::shared_ptr<Node> ptr)
    {
        m_ptr = ptr;
    }
private: 
    boost::shared_ptr<Node> m_ptr;
};
int main()
{
    boost::shared_ptr<Node> bc_ptr(new Node());
    bc_ptr->storeChild(bc_ptr); // this line is the bug 
    return 0;
}

我的问题是:1. 节点对象是否被删除?我知道智能指针应该管理这些东西,所以我们不必删除。但看起来使用 storeChild 传递到类中的引用永远不会重置。这是否意味着我将出现内存泄漏?2. 有没有办法使用智能指针来防止这种情况发生?显然,应该为storeChild方法提供一个指向不同节点的指针,但是您如何防止这种情况?

如果我运行这个程序,析构函数永远不会被调用。

是的,这是内存泄漏,因为Node中的共享指针永远不会被删除。考虑:

#include <iostream>
#include <memory>
class Node {
    std::shared_ptr<Node> m_ptr;
public:
    Node() { std::cout << "constructorn"; }
    ~Node() { std::cout << "destructorn"; }
    void storeChild(std::shared_ptr<Node> ptr) { m_ptr = ptr; }
    long use_count() { return m_ptr.use_count(); }
};
int main() {   
    Node* n = new Node;
    {
        std::shared_ptr<Node> bc_ptr(n);
        bc_ptr->storeChild(bc_ptr); // this line is the bug
        std::cout << n->use_count() << "n";     // prints 2
    }
    std::cout << n->use_count() << "n";         // prints 1
    // the Node pointed to by n is leaked
}

如果你这样做,可能会更明显:

#include <iostream>
#include <memory>
class Node {
    std::shared_ptr<Node> m_ptr;
public:
    Node() : m_ptr(this) { std::cout << "constructorn"; }
    ~Node() { std::cout << "destructorn"; }
};
int main() {
    new Node;
}

如果您尝试:

int main() {
    delete new Node;
}

Node析构函数将被调用两次。首先是您的delete,其次是删除时的shared_ptr

如果最终有可能获得循环所有权,那么防止它可能会很棘手,例如:A->B->C->A ...如果存在风险,您可能应该使用std::weak_ptr