【问题标题】:How to recover memory leak from dynamic allocation in C++?如何从 C++ 中的动态分配中恢复内存泄漏?
【发布时间】:2019-08-15 07:06:59
【问题描述】:

如果我写:

b = new int;
b = new int; 
delete b;

我知道delete b; 只会从内存中删除第二个b。由于删除后没有任何内容指向第一个b,因此存在内存泄漏。

在这种情况下,我知道有一种方法可以在 C# 和 Java 中恢复这种泄漏。有没有办法在 C++ 中恢复这种内存泄漏?

【问题讨论】:

  • 在遵守标准 C++ 时不会。一旦你失去了对动态分配的最后一个引用,你就完蛋了。
  • @user4581301 我明白了。谢谢。
  • 不用担心。要点是避免原始动态分配。使用containerssmart pointers 为您处理内存。如果不能,请使用RAII 包装分配并观察Rule of Three or Five
  • 删除“第二个b”并不是导致“第一个b”泄露的原因。 b = new int 的第二个赋值是做什么的,不管后面是否跟delete bdelete b 只是释放第二个 new 表达式的结果。
  • @user4581301 对。我真的需要更适应使用智能指针。我想我的一位教授也谈到了它。

标签: c++ memory memory-leaks heap-memory dynamic-memory-allocation


【解决方案1】:

我知道有办法在 C# 和 Java 中恢复这种内存泄漏

Java 和 C# 都是垃圾收集语言,因此它们不会经常发生内存泄漏(几乎不可能),但是当它们发生时,您可以抛出异常,

有没有办法在 C++ 中恢复这种内存泄漏?

在 C++ 中,内存泄漏更为常见,因为每次创建指针时都会手动分配内存,因此您总是会抛出异常来指出内存泄漏是否发生在哪里,在哪里以及如何处理它......所以你的问题的答案是......不,你无法从 C++ 中的内存泄漏中恢复,它是一种“Down To The Metal”语言,这就是为什么如果编写不正确它如此脆弱,但你总是可以抛出确实发生内存泄漏时的例外情况,您可以查明它并查看如何修复它。

【讨论】:

    【解决方案2】:

    选项 1

    最简单的方法是完全避免newdelete

    代替:

    b = new int;
    b = new int; 
    delete b;
    

    写:

    std::unique_ptr<int> b;
    ...
    b = std::make_unique<int>();
    b = std::make_unique<int>(); 
    

    b 被覆盖或超出范围时,它会释放内存。不需要甚至不允许使用 delete。注意很像 Java 垃圾收集器,但大多数时候都足够好。

    选项 2。

    另一种方法是使用add-on garbage collector,但不建议使用该解决方案。首先,垃圾收集器是保守的,这意味着尽管有垃圾收集器,但仍有可能发生内存泄漏。其次,这些解决方案往往会使现有问题变得更糟,因为内存泄漏在引入时不会被注意到和处理。引入一年后处理内存泄漏比引入后一个小时处理要困难几个数量级。

    注意:使用 unique_ptr 不如在 C#、Java 和 Python 等垃圾收集语言中安全。当没有明确的所有权模型并且存在循环所有权时,它就会失败。如果元素a 有一个unique_ptrb 并且b 有一个unique_ptra,那么它们将永远不会被释放。它们永远不会被释放,因为unique_ptr 释放了析构函数中的对象,但没有人会调用ab 的析构函数。如果没有人调用析构函数,那么unique_ptr将永远不会删除该对象,也永远不会调用另一个对象的析构函数。

    注意 2:有时应该使用 std::shared_ptr 而不是 unique_ptr,但这并不能解决循环引用的问题。这只解决了单个对象的多个所有者的问题。

    注意 3:由于析构函数中的深度递归,这些智能指针不会降低堆栈溢出的可能性。这很可能发生在长链表的递归破坏或不平衡的二叉树中。在这种情况下使用unique_ptr 只是隐藏了递归正在发生的事实。

    【讨论】:

    • 好的,我明白了。因此,在 C++ 中,似乎没有绝对确定的替代方案可以替代遵循传统做法,即注意我们如何动态分配内存,以及一旦我们使用完数据后,我们可以如何保护一种清除内存的方法。我们的程序结束。感谢您的详细解释。
    • @JohnPark 是的,但是有很多自动化。在大多数情况下,您需要注意的只是谁拥有什么。你很少需要考虑谁分配和释放东西。这一切只要你避免 new/malloc
    猜你喜欢
    • 2016-12-11
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多