【问题标题】:What happens when you deallocate a pointer twice or more in C++?在 C++ 中释放指针两次或更多次时会发生什么?
【发布时间】:2011-02-14 08:34:21
【问题描述】:
int main() {
    Employee *e = new Employee();

    delete e;
    delete e;
    ...
    delete e;
    return 0;
}

【问题讨论】:

  • out of cucumber 错误重启 Universe。
  • 为什么投反对票?这是一个简单直接的问题。仅仅因为你认为这是一个基本问题并不意味着它应该被 d/v'ed。

标签: c++ pointers memory-management allocation delete-operator


【解决方案1】:

如果您多次尝试通过指针delete 一个对象,则会得到未定义的行为

这意味着几乎任何事情都可能发生,从“看起来工作”到“崩溃”或完全随机的事情。

【讨论】:

  • 我试过了,没有崩溃。但我认为您可能会释放程序其他部分正在使用的内存。
  • 此时可能不会崩溃。但是,如果它破坏了堆的一部分,那么之后很可能会在某个任意时间点发生崩溃。然而,它可能会成为一个潜伏的定时炸弹。直到后来一些看似无关的动作碰巧碰到损坏的部分然后 boom 才引起任何问题
【解决方案2】:

这是不安全的,也不确定实际会发生什么:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2

【讨论】:

    【解决方案3】:

    您可能会冒险进入“未定义行为”领域。

    在许多系统上,这会导致崩溃;例如,在我的 Linux 机器上:

    *** glibc detected *** ./cctest: double free or corruption (fasttop): 0x0000000000d59900 ***
    ======= Backtrace: =========
    /lib/libc.so.6[0x7f399f4cbdd6]
    /lib/libc.so.6(cfree+0x6c)[0x7f399f4d074c]
    ./cctest[0x400a7a]
    /lib/libc.so.6(__libc_start_main+0xfd)[0x7f399f474abd]
    ./cctest[0x400959]
    

    【讨论】:

      【解决方案4】:

      除了关于“未定义行为”的旧观点,这意味着任何事情都可能发生,从无到有通往地狱第七圈的大门在主内存中打开,实际上大多数情况下通常会发生什么实现是程序将继续运行超过删除,然后在稍后的某个不相关的内存分配中神秘地崩溃。

      【讨论】:

      • 是的,这是可以发生的更好的事情之一。
      • 经常当我得到神秘的内存崩溃时,我希望一个通往地狱第七圈的通道已经在主内存中打开了......
      【解决方案5】:

      这是未定义的行为,所以任何事情都可能发生。

      可能发生的事情很糟糕。通常,免费存储是一个精心管理的免费和已分配块系统,newdelete 进行簿记以使所有内容保持一致状态。如果你再次delete,系统很可能对无效数据做同样的记账,突然空闲存储处于不一致状态。这称为“堆损坏”。

      一旦发生这种情况,您对newdelete 所做的任何事情都可能会产生不可预知的结果,其中可能包括尝试在应用程序的内存区域之外进行写入、默默地破坏数据、错误地认为没有更多内存、重复或重叠分配。如果你幸运的话,程序很快就会崩溃,尽管你仍然很难找出原因。如果你运气不好,它会继续运行,结果很糟糕。

      【讨论】:

        【解决方案6】:

        如果你真的很幸运,它会崩溃。通常发生的情况是,它会存储业力,直到您的 CEO 向您最重要的新客户展示代码时,它会破坏/破坏他们的所有数据。

        在检查或调试版本中经常会发现这种事情,但它可能会完全未被发现并在以后造成严重破坏。当涉及多个线程时,这一点尤其重要。

        【讨论】:

          【解决方案7】:

          如果您担心这可能会在您的应用程序中发生,请完全停止使用原始指针,这样您就不需要删除(例如切换到 shared_ptr)或始终将指针设置为 NULL(或 0,或者更好的是nullptr) 删除它们后。对空指针调用 delete 保证什么都不做。

          【讨论】:

          • 我一直不喜欢后一种解决方案。删除一个指针两次是不好的,将指针设置为 null 只是为了隐藏问题。
          【解决方案8】:

          尽管有时我们可以在删除 ptr 后访问内存位置。 我们不应该再次删除相同的指针或为该指针赋值(导致不一致的行为)。

          但是我们可以使用相同的指针变量指向不同的内存地址(有效内存)

          int *p = new int(10);
          std::cout << "in main" << std::endl;
          std::cout <<*p << std::endl;
          std::cout << p << std::endl;
          std::cout << &p<< std::endl;
          delete p;
          std::cout << "in main2 after delete" << std::endl;
          std::cout <<*p << std::endl;
          std::cout << p << std::endl;
          std::cout << &p<< std::endl;
          
          p = new int(100);
          std::cout << "in main3" << std::endl;
          std::cout <<*p << std::endl;
          std::cout << p << std::endl;
          std::cout << &p<< std::endl;
          

          导致输出

          in main
          10
          0x558b597a8eb0
          0x7fff8f7a5ba0
          in main2 after delete
          0
          0x558b597a8eb0
          0x7fff8f7a5ba0
          in main3
          100
          0x558b597a8eb0
          0x7fff8f7a5ba0
          

          【讨论】:

            猜你喜欢
            • 2013-10-26
            • 1970-01-01
            • 2015-08-18
            • 2016-08-21
            • 2017-02-07
            • 1970-01-01
            • 1970-01-01
            • 2010-12-02
            • 1970-01-01
            相关资源
            最近更新 更多