6

I know that std::unique_ptr doesn't guarantee memory safety and especially it is true in the case of circular dependency. However, in my case, I can't see it. Child contain Parent(or SecondChild in case of polymorphism), but neither of them contains Child.

Valgrind reports 4 bytes lost so I suppose that SecondChild was not destroyed. My code really relies on polymorphism so I hope to get advice on refactoring that won't change Parent* in Child.

#include <iostream>
#include <memory>
using namespace std;

struct Parent
{
    Parent() {
        cout << "Expr created" << endl;
    }

    ~Parent() {
        cout << "Expr destroyed" << endl;
    }
};

struct Child : public Parent 
{
    std::unique_ptr<Parent> content;
};

struct SecondChild : public Parent 
{
    int val;
};

std::unique_ptr<Parent> foo()
{
    auto test = make_unique<Child>();
    auto content_in_child = make_unique<SecondChild>();
    content_in_child->val = 4;
    test->content = std::move(content_in_child);
    return test;
}

int main()
{
    std::unique_ptr<Parent> high = foo();
    return 0;
}
JeJo
  • 30,635
  • 6
  • 49
  • 88
MegaRaman
  • 100
  • 4
  • 4
    `Parent` should have a virtual destructor. If a program deletes a pointer to a derived type through a pointer to a base and the destructor of the base isn't virtual the behavior of the program is undefined. – Pete Becker Jul 02 '23 at 21:01
  • note - `shared_ptr` "remembers" the real type and doesn't require a virtual destructor, while `unique_ptr` does need the virtual destructor – M.M Jul 02 '23 at 21:57

1 Answers1

7

You have undefined behavior, due to the fact that the parent class is missing a virtual destructor, and you are deleting Child objects (i.e. test from foo()) through base class pointers (i.e. std::unique_ptr<Parent>).

Undefined behavior means that anything can happen. In your case, it is a memory leak. Fix it by adding a virtual destructor.

struct Parent {
     // ....
    virtual ~Parent() {
    //^^^^^^              -----> required !!
    // ...
    }
};

Read more:

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
JeJo
  • 30,635
  • 6
  • 49
  • 88