【问题标题】:Leaking memory when assigning new value to variable?为变量分配新值时内存泄漏?
【发布时间】:2011-08-08 13:27:08
【问题描述】:

是的,我是那些从 Java 学习 C++ 的人之一,被自动垃圾收集器宠坏了。有一种特殊情况,我想知道我是否在泄漏内存。让我们在 C++ 中考虑:

bool *test = new bool(false);
test = new bool(true);
delete test;

我在这里泄漏内存了吗?或者我应该在分配新值之前先致电delete?像这样:

bool *test = new bool(false);
delete test;
test = new bool(true);
delete test;

我的直觉告诉我第一个是正确的,因为指针test 指向内存中的同一地址,并为其变量分配新值,不会更改此地址。或者new 运算符是否在内存中分配了不同的地址?谁能给我一个线索,还是我都弄错了?

【问题讨论】:

  • 回复:“是的,我是那些正在学习来自 Java 的 c++ 的人之一。”然后我强烈建议您选择a good introductory C++ book 并假装您从未学过Java。 C++ 不是 Java。尝试在 C++ 中像 Java 一样编程只会导致眼泪和挫败感。 It's like using RegEx to parse HTML.
  • “被宠坏了”是一种委婉说法,如果我听说过的话。
  • 很可能这正是他正在做的事情。
  • 你真的需要在堆上分配'bool'吗?尤其是内置类型的单个值在堆上分配非常少见。在普通的 C++ 程序中,“new”的使用比在普通的 Java 程序中要少得多!
  • C++ 有自己的 GC 系统,其行为比 Java 更精细。你只需要使用它。使用std::shared_ptr<int> 而不是int*,您的所有问题都会随着垃圾收集器的工作而消失。但是您甚至不需要动态分配对象。只需使用bool 而不是bool*

标签: c++ memory pointers new-operator memory-leaks


【解决方案1】:

是的,您正在泄漏,而 c++ 的方法是:

bool test = false;
test = true; 

// ta-da - no leak.

您可以采用第二种方法 - 但是您可能会皱起眉头...

【讨论】:

  • @amit 很好,对于内置类型,我会坚持使用 Nim 的选项。
  • @amit:为什么一个人会返回对局部变量的引用?
  • @amit:正确。我认为 Nim 试图达到的是变量的自动分配首选动态分配。
  • @In Silicio, Nim:我同意静态分配在可能的情况下是可取的,但并非总是如此。在我看来,OP确实是一个初学者,他目前正在学习动态分配。在我看来,学习动态分配时“使用静态分配”的解决方案不是解决方案。
  • @amit 在我看来,这似乎更有可能来自引用计数、垃圾收集、“新的一切”Java,OP 不习惯使用惯用的 C++ 声明局部变量的方式.
【解决方案2】:

是的,确切地说,您必须先delete,然后再覆盖地址。或者更好的是在堆栈上分配或使用智能指针。

【讨论】:

    【解决方案3】:

    你确实被宠坏了。

    问题是你没有区分地址和变量。


    bool *test = new bool(false);
    
    • test分配具有自动持续时间的空间
    • 为 bool 分配具有动态持续时间的空间
    • false写进这个空间
    • 将此空间的地址存入test

    test = new bool(true);
    
    • 为 bool 分配具有动态持续时间的空间
    • true到这个空间
    • 把这个空间的地址存入test(之前存的地址被无情的丢弃了,因为它没有存到别的地方,它指向的内存永远都不能回收,说明你有泄漏)。李>

    delete test;
    
    • 读取存储到test中的地址
    • 在这个地址释放空间

    我的直觉告诉我第一个是正确的,因为指针测试指向内存中的同一地址,并为其变量分配一个新值,不会改变这个地址。还是 new 运算符在内存中分配了不同的地址?

    从语义上讲,您应该考虑new 总是将地址返回到内存中的new 空间(显然是错误的,因为内存被重用)。这就是为什么对new 的每次调用都需要与恰好一个delete 的调用匹配。

    因此,您的直觉是错误的,new 不会“仅”创建一个变量。如果您来自 Java,这可能确实令人震惊,您需要一个强大的教程来掌握编程的精髓。

    【讨论】:

      【解决方案4】:

      是的,您正在泄漏内存。对于每个new,应该有一个后续的delete。如果您用新地址覆盖指针,那么您将失去将分配与delete 配对的机会。

      【讨论】:

        【解决方案5】:

        是的,您的第一个示例实际上是内存泄漏。 每个new 的调用都必须有一个对delete 的匹配调用(除非new 失败)。

        在 C++ 中,执行您似乎想要做的事情的正常方法是简单地在本地声明 bool:

        bool b = truel
        b = false;
        

        但是,如果您出于某种原因确实需要动态分配,则可以使用智能指针来管理内存,因此您不必担心调用delete。你可以查一下scoped_ptrunique_ptrshared_ptr

        最后,C++ 有一个很棒的标准库,可以处理许多可能的容器和算法,让您不必重新发明它们,并让您不必在各种情况下处理动态分配。

        如果您认真学习 C++,我会从 SO C++ 书籍列表中挑选一本书并从头开始学习,而不是尝试将 Java 习语转移到 C++(它不会很好用)。

        【讨论】:

          【解决方案6】:

          bool 是一种内置数据类型。为什么需要这样分配内存?你可以很容易地在堆栈上分配

          【讨论】:

            【解决方案7】:

            是的,在第一种情况下您正在泄漏内存。第二种方法是正确的方法。在您的第一种情况下...

            当您第二次调用 new 时,第一次分配超出范围,但仍然存在。在 Java 中,这很好,因为 GC 会为您清理它。然而,在 C++ 中,没有这样的原始指针。

            每次调用 new 时都必须调用 delete。另外,删除指针后,将其设置为 null 或 0。这样可以防止您意外删除无效内存。

            【讨论】:

              猜你喜欢
              • 2013-07-06
              • 2011-03-20
              • 2013-10-16
              • 2021-09-21
              • 1970-01-01
              • 2016-09-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多