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

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

Memory leak using unique pointer and polymorphism

问题

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

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

  1. #include <iostream>
  2. #include <memory>
  3. using namespace std;
  4. struct Parent
  5. {
  6. Parent() {
  7. cout << "Expr created" << endl;
  8. }
  9. ~Parent() {
  10. cout << "Expr destroyed" << endl;
  11. }
  12. };
  13. struct Child : public Parent
  14. {
  15. std::unique_ptr<Parent> content;
  16. };
  17. struct SecondChild : public Parent
  18. {
  19. int val;
  20. };
  21. std::unique_ptr<Parent> foo()
  22. {
  23. auto test = make_unique<Child>();
  24. auto content_in_child = make_unique<SecondChild>();
  25. content_in_child->val = 4;
  26. test->content = std::move(content_in_child);
  27. return test;
  28. }
  29. int main()
  30. {
  31. std::unique_ptr<Parent> high = foo();
  32. return 0;
  33. }
英文:

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.

  1. #include &lt;iostream&gt;
  2. #include &lt;memory&gt;
  3. using namespace std;
  4. struct Parent
  5. {
  6. Parent() {
  7. cout &lt;&lt; &quot;Expr created&quot; &lt;&lt; endl;
  8. }
  9. ~Parent() {
  10. cout &lt;&lt; &quot;Expr destroyed&quot; &lt;&lt; endl;
  11. }
  12. };
  13. struct Child : public Parent
  14. {
  15. std::unique_ptr&lt;Parent&gt; content;
  16. };
  17. struct SecondChild : public Parent
  18. {
  19. int val;
  20. };
  21. std::unique_ptr&lt;Parent&gt; foo()
  22. {
  23. auto test = make_unique&lt;Child&gt;();
  24. auto content_in_child = make_unique&lt;SecondChild&gt;();
  25. content_in_child-&gt;val = 4;
  26. test-&gt;content = std::move(content_in_child);
  27. return test;
  28. }
  29. int main()
  30. {
  31. std::unique_ptr&lt;Parent&gt; high = foo();
  32. return 0;
  33. }

答案1

得分: 7

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

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

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

  1. struct Parent {
  2. // ....
  3. virtual ~Parent() {
  4. //^^^^^^ -----&gt; 必须添加 !!
  5. // ...
  6. }
  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&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.

  1. struct Parent {
  2. // ....
  3. virtual ~Parent() {
  4. //^^^^^^ -----&gt; required !!
  5. // ...
  6. }
  7. };

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:

确定