遇到这个错误,其中一个类包含一个指向自身的指针-并且它指向同一实例。这是包含该问题的最小代码段...
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.是否删除了Node对象?我知道智能指针应该可以管理那些事情,所以我们不必删除。但看起来使用storeChild
传递给类的引用永远不会重置。这是否意味着我将发生内存泄漏?
2.有没有使用智能指针的方法来防止这种情况发生?显然,应该为storeChild
方法提供一个指向其他Node的指针,但是如何防止这种情况呢?
如果运行此程序,则不会调用析构函数。
答案 0 :(得分:1)
是的,这是内存泄漏,因为Node
中的共享指针永远不会被删除。考虑:
#include <iostream>
#include <memory>
class Node {
std::shared_ptr<Node> m_ptr;
public:
Node() { std::cout << "constructor\n"; }
~Node() { std::cout << "destructor\n"; }
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 << "constructor\n"; }
~Node() { std::cout << "destructor\n"; }
};
int main() {
new Node;
}
如果您尝试:
int main() {
delete new Node;
}
Node
析构函数将被调用两次。首先是您的delete
,然后是shared_ptr
(在删除时)。
如果可能以循环所有权结尾,则防止它很棘手,例如:A-> B-> C-> A ...如果有风险,您可能应该使用std::weak_ptr
。