samedi 2 novembre 2019

How does `std::shared_ptr` cyclic dependency cause a problem

I found several related questions, but I couldn't find an explanation regarding "how" this happens.

I have the following code, which is one step behind the version that can create a cyclic shared_ptr reference problem. (Adding b.other = a; before return causes the problem)

For better clarification, I added comments on important lines to indicate the state of the program at that point.

#include <iostream>
#include <memory>

using namespace std;

struct Foo
{
    explicit Foo(char i) : id{i} { cout << "Constructed " << id << endl; }
    ~Foo() { cout << "Destructed " << id << endl; }

    shared_ptr<Foo> other = {};
    char const id;
};

int main()
{
    auto const a = make_shared<Foo>('a'); // a_use_count = 1, b_use_count = 0
    auto const b = make_shared<Foo>('b'); // a_use_count = 1, b_use_count = 1

    a->other = b; // a_use_count = 1, b_use_count = 2

    return 0;     // What happens now? Following is my "expectation" (which is wrong !)
                  // 1. destruct b => a_use_count = 1, b_use_count = 1
                  // 2. destruct a (in following order)
                  //    2.1 destruct a.other => b_use_count = 0 => show "Destructed b"
                  //    2.2 destruct a       => a_use_count = 0 => show "Destructed a"
}

However, things do not happen as I expect. a and b gets destructed in the opposite order. I am seeing the following output.

Constructed a
Constructed b
Destructed a
Destructed b

What exactly happens when the program returns above? (I hope understanding this will help understanding the cyclic dependency problem)

Aucun commentaire:

Enregistrer un commentaire