【问题标题】:Memory leak issue; deleting a pointer内存泄漏问题;删除指针
【发布时间】:2011-02-25 10:07:00
【问题描述】:

如果我有一个指向堆中特定内存地址的指针。我希望这个 same 指针指向另一个内存地址,我应该先delete 指针吗?但是,在这种情况下,我实际上是在删除指针还是只是破坏了指针指向的引用(内存地址)?

所以,换句话说,如果我delete 是一个指针,这是否意味着它不再存在?或者,它在那里,但没有指出它在哪里?

【问题讨论】:

  • 除了给出的答案之外,请注意 C++ 还有 new[] 和 delete[] 运算符,它们不只是分配/删除一个对象,而是整个数组。这是该语言的一个非常愚蠢的功能,因为它很容易在忘记 [] 时造成内存泄漏。到目前为止,最好的解决方案是根本不使用 new/delete,而是使用智能指针类:en.wikipedia.org/wiki/Smart_pointer

标签: c++ pointers delete-operator


【解决方案1】:

delete 的语法有点误导。当你写

T* ptr = /* ... */
delete ptr;

没有删除变量ptr。相反,您正在删除ptr 指向的对象。 ptr 的值没有改变,它仍然指向它以前的位置,所以你应该确保在没有先重新分配它之前不要取消引用它。

在重新分配指针之前,不要求您 delete 指针。但是,您应该确保,如果您要重新分配指针,导致您丢失对所指向对象的最后引用(例如,如果此指针是程序中指向其指针对象的唯一指针),那么你应该delete它以确保你不会泄漏内存。

许多 C++ 程序员用来简化何时释放内存的逻辑的一种技术是使用 smart pointers,该对象重载了模仿指针所需的运算符,并且具有自动执行以帮助跟踪资源的自定义代码。例如,新的 C++0x 标准将为此提供 shared_ptrunique_ptr 类型。 shared_ptr 的作用类似于常规指针,不同之处在于它跟踪资源中有多少 shared_ptrs。当资源的最后一个shared_ptr 更改它指向的位置(通过重新分配或被销毁)时,它会释放资源。例如:

{
    shared_ptr<int> myPtr(new int);
    *myPtr = 137;
    {
       shared_ptr<int> myOtherPtr = myPtr;
       *myPtr = 42;
    }
}

请注意,此代码中没有任何地方调用delete 来匹配对new 的调用!这是因为shared_ptr 足够聪明,可以注意到最后一个指针何时停止指向资源。

在使用智能指针时需要注意一些特性,但它们非常值得花时间学习。一旦了解了它们的工作原理,就可以编写更简洁的代码。

【讨论】:

    【解决方案2】:

    当你delete一个指针时,你释放分配给指向对象的内存。所以如果你只是想让你的指针指向一个新的内存位置,你应该 delete 指针。但是如果你想销毁它当前指向的对象,然后再指向另一个对象,那么你应该delete指针。

    【讨论】:

      【解决方案3】:

      xtofl,虽然很有趣,但有点正确。

      如果你“新”了一个内存地址,那么你应该删除它,否则不要管它。也许你想太多了,但你是这样想的。是的,记忆一直都在,但如果你在它周围设置了一道栅栏,你需要把栅栏拆掉,否则没有人能做到。

      【讨论】:

      • 我认为这应该是最简单的规则:一新 == 一删除。不要再打扰了。但是尽量避免新闻;)
      【解决方案4】:

      当您调用 delete 时,您将指针指向的内存标记为空闲 - 堆获得它的所有权并可以重用它,仅此而已,the pointer itself is usually unchanged

      如何处理指针取决于你想要什么。如果您不再需要该内存块 - 使用 delete 释放该块。如果您以后需要它 - 将地址存储在您以后可以检索到的地方。

      【讨论】:

        【解决方案5】:

        要直接回答您的问题,之前有人问过这个问题。 delete 将删除您的指针指向的内容,但 Bjarne Stroustrup 建议不再依赖指针本身的值,特别是如果它是左值。但是,这不会影响重新分配它的能力,因此这将是有效的:

        for( p = first; p != last; ++p )
        {
           delete p;
        }
        

        如果您正在迭代一个指针数组,所有这些指针都已使用new 分配。

        C++ 中的内存管理最好使用一种称为 RAII 的技术来完成,“资源获取就是初始化”。

        这实际上意味着,在您分配资源时,您会立即处理它的生命周期,即您通过将其放入某个对象中来“管理”它,该对象将在不再需要时为您删除它。

        shared_ptr 是一种常用的技术,其中资源将在许多地方使用,并且您不确定哪个将是最后一个“释放”它,即不再需要它。

        shared_ptr 经常在其他地方使用,只是为了它的语义,即你可以很容易地复制和分配它们。

        还有其他内存管理智能指针,特别是 std::auto_ptr 将被 unique_ptr 取代,还有 scoped_ptr。 weak_ptr 是一种方法,可以在某个地方存在 shared_ptr 时获得它,但自己不持有引用。您调用“lock()”,它会为您提供一个 shared_ptr 到内存,或者如果所有当前共享指针都已消失,则为 NULL。

        对于数组,通常不会使用智能指针,而只是使用向量。

        对于字符串,您通常会使用字符串类,而不是将其视为 char 的向量。

        【讨论】:

          【解决方案6】:

          简而言之,您不是“删除指针”,而是删除指针指向的任何内容。

          这是一个经典问题:如果您删除它,而其他人指向它,他们将读取垃圾(并且很可能会导致您的应用程序崩溃)。另一方面,如果你不这样做并且这是最后一个指针,你的应用程序将泄漏内存。

          此外,指针可能指向最初不是由“new”分配的东西,例如一个静态变量,堆栈上的一个对象,或另一个对象的中间。在所有这些情况下,您都不允许删除指针指向的任何内容。

          通常,在设计应用程序时,您(是的,您)必须决定应用程序的哪个部分拥有特定对象。它,而且只有它,应该在它完成后删除对象。

          【讨论】:

            猜你喜欢
            • 2021-06-14
            • 1970-01-01
            • 2019-03-31
            • 1970-01-01
            • 2013-11-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多