内存泄漏使用唯一指针和多态性

huangapple go评论65阅读模式
英文:

Memory leak using unique pointer and polymorphism

问题

我知道std::unique_ptr不保证内存安全,尤其在循环依赖的情况下更是如此。然而,在我的情况下,我看不到这个问题。Child 包含 Parent(或者在多态的情况下是 SecondChild),但它们都不包含 Child

Valgrind 报告了丢失了 4 个字节,所以我认为 SecondChild 没有被销毁。我的代码依赖于多态性,所以我希望能够得到关于重构的建议,而不会改变 Child 中的 Parent*

#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;
}
英文:

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 &lt;iostream&gt;
#include &lt;memory&gt;
using namespace std;

struct Parent
{
    Parent() {
        cout &lt;&lt; &quot;Expr created&quot; &lt;&lt; endl;
    }

    ~Parent() {
        cout &lt;&lt; &quot;Expr destroyed&quot; &lt;&lt; endl;
    }
};

struct Child : public Parent 
{
    std::unique_ptr&lt;Parent&gt; content;
};

struct SecondChild : public Parent 
{
    int val;
};

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

int main()
{
    std::unique_ptr&lt;Parent&gt; high = foo();
    return 0;
}

答案1

得分: 7

你的代码存在未定义行为,这是因为父类缺少虚析构函数,而你通过基类指针(即std::unique_ptr&lt;Parent&gt;)删除了Child对象(即foo()中的test)。

未定义行为意味着任何事情都可能发生。在你的情况下,这会导致内存泄漏。

通过添加虚析构函数来修复它

struct Parent {
    // ....
    virtual ~Parent() {
    //^^^^^^              -----&gt; 必须添加 !!
    // ...
    }
};

阅读更多:

英文:

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&lt;Parent&gt;).

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() {
    //^^^^^^              -----&gt; required !!
    // ...
    }
};

Read more:

huangapple
  • 本文由 发表于 2023年7月3日 04:57:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600776.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定