为什么在boost :: shared_ptr中使用循环引用时内存泄漏

时间:2015-07-18 05:04:05

标签: c++ memory-leaks boost-smart-ptr

在以下代码内存泄漏发生时,我对此表示怀疑。在测试()乐趣:

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

class parent;
class children;

typedef boost::shared_ptr<parent> parent_ptr;
typedef boost::shared_ptr<children> children_ptr;

class parent
{
public:
    ~parent() { std::cout <<"destroying parent\n"; }

public:
    children_ptr children;
};

class children
{
public:
    ~children() { std::cout <<"destroying children\n"; }

public:
    parent_ptr parent;
};

void test()
{
    parent_ptr father(new parent());
    children_ptr son(new children);

    father->children = son;// parent_ptr_count=1, children_ptr_count=2
    son->parent = father;// parent_ptr_count=2, children_ptr_count=2
   //1,2,3 See the note below
}

void main()
{
    std::cout<<"begin test...\n";
    test();
    std::cout<<"end test.\n";
}
  1. // childern_ptr从堆栈弹出,我认为childern_ptr_count--和parent_ptr_count -

  2. // parent_ptr从堆栈中弹出,我认为childern_ptr_count--和parent_ptr_count -

  3. //但事实上,它没有那样做,为什么?

  4. 我希望有人可以帮助我,非常感谢你。

3 个答案:

答案 0 :(得分:0)

我相信这正是本例中的情景:https://visualstudiomagazine.com/articles/2012/10/19/circular-references.aspx

这是一个循环引用,解决方案是让其中一个指针成为弱指针。虽然这篇文章是针对C ++ 11的共享和弱指针的实现,但出于完全相同的原因,boost也有一个弱指针。

答案 1 :(得分:0)

son被销毁时,children对象的引用计数会下降,但parent对象的引用计数不会,因为children对象包含parent_ptr未被销毁(因为它的引用计数为1,而不是0)。

同样,当father被销毁时,parent对象的引用计数会下降,但children对象的引用计数不会,因为parent包含children_ptr的对象未被销毁(因为其引用计数为1,而不是0)。

答案 2 :(得分:0)

与其他答案建议一样,您已创建a circular reference

这是一个解决方案。当指针指向彼此时,使用weak_ptr通常很有用。这样做会使指针成为shared_ptr,当它不是shared_ptr时,它不会增加引用计数,因此允许对象被销毁。

以下是一个例子:

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

class parent;
class children;

typedef boost::shared_ptr<parent> parent_ptr;
typedef boost::shared_ptr<children> children_ptr;

typedef boost::weak_ptr<parent> parent_weak_ptr;
typedef boost::weak_ptr<children> children_weak_ptr;

class parent
{
public:
    ~parent() { std::cout <<"destroying parent\n"; }

public:
    children_weak_ptr children;
};

class children
{
public:
    ~children() { std::cout <<"destroying children\n"; }

public:
    parent_weak_ptr parent;
};

void test()
{
    parent_ptr father(new parent());
    children_ptr son(new children);

    father->children = son;// parent_ptr_count=1, children_ptr_count=1
    son->parent = father;// parent_ptr_count=1, children_ptr_count=1
}

void main()
{
    std::cout<<"begin test...\n";
    test();
    std::cout<<"end test.\n";
}

使用此代码,子级和父级将被销毁,并且他们可以使用lock()上的weak_ptr函数相互访问,将其转换为shared_ptr。这是一些文档:

boost::weak_ptr docs

std::weak_ptr docs