0

in the follow code memory leak happened, I have my doubt about that. in the test() fun:

#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 pop from stack, I think the childern_ptr_count-- and parent_ptr_count--

  2. // parent_ptr pop from stack, I think the childern_ptr_count-- and parent_ptr_count--

  3. // but in fact, it didn't do that, why?

I hope someone can help me, thank you very much.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
yuan su
  • 1
  • 1
  • Because C++ doesn't have a grand framework that can detect circular references. Each shared pointer operates individually and can only attempt to deallocate the pointee when itself is deallocated first. – TheUndeadFish Jul 18 '15 at 05:39

3 Answers3

0

I believe this is exactly the scenario in this example: https://visualstudiomagazine.com/articles/2012/10/19/circular-references.aspx

This is a cyclic reference, and the solution is to have one of the pointers be a weak pointer. Although the article is for C++11's implementation of shared and weak pointers, boost also has a weak pointer for the exact same reason.

mock_blatt
  • 955
  • 5
  • 11
0

When son is destroyed, the reference count for the children object goes down, but the reference count for the parent object does not, because the children object that contains the parent_ptr was not destroyed (because its reference count is 1, not 0).

Likewise, when father is destroyed, the reference count for the parent object goes down, but the reference count for the children object does not, because the parent object that contains the children_ptr was not destroyed (because its reference count is 1, not 0).

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
0

Like the other answers suggest, you have created a circular reference.

Here's a solution. When you have pointers pointing to each other, it can often be useful to use a weak_ptr. What this does is makes a pointer that you can turn into a shared_ptr, and when it's not a shared_ptr it doesn't increment the reference count, therefore allowing the objects to be destroyed.

Here's an example:

#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";
}

With this code, the children and parent are destroyed, AND they can access each other using the lock() function on the weak_ptr to turn it into a shared_ptr. Here's some docs:

boost::weak_ptr docs

std::weak_ptr docs

Community
  • 1
  • 1
Russell Greene
  • 2,141
  • 17
  • 29