【问题标题】:Dynamic memory allocation "delete"动态内存分配“删除”
【发布时间】:2011-06-17 16:29:11
【问题描述】:

如果我为int 对象动态分配内存位置,如下所示:

int *x = new int;

完成后,想要释放堆上的内存,我将执行以下操作:

delete x;

现在,如果我做了,请执行以下操作:

x = NULL;

x 会指向另一个地址吗? 更新: another 而不是 many

说我没有做x = NULL并做了另一个 delete x;,会发生什么?

【问题讨论】:

标签: c++ heap-memory dynamic-memory-allocation delete-operator


【解决方案1】:
  1. 删除 x= NULL 除外 - 这是 imo,不好的做法)在您删除它后所做的任何事情都是未定义的。
  2. 双重删除 = 灾难。

注意:一些运行时系统会 保护你免受某些非常简单的 双重删除的情况。根据 细节,你可能没问题,如果你 碰巧在其中一个上运行 系统,如果没有人部署 您在另一个系统上的代码 以不同的方式处理事情,如果你 正在删除没有的东西 有一个析构函数,如果你不这样做 两者之间任何重要的事情 删除,如果没有人改变 你的代码做一些重要的事情 在两次删除之间,如果您的 线程调度程序(你在它上面 可能无法控制!)没有 碰巧在两者之间交换线程 删除 and if, and if, and if.所以 回到墨菲:因为它可能出错, 会的,而且会出错 最糟糕的时刻。

https://isocpp.org/wiki/faq/freestore-mgmt

【讨论】:

    【解决方案2】:

    第二次删除未定义。

    附带说明,有一些工具可以检测双重删除。周围最好的之一是Valgrind

    【讨论】:

      【解决方案3】:

      类型:

      int main(){
        int* i = new int;
        std::cout << i << std::endl;
        delete i;
        std::cout << i << std::endl;
        delete i;
      }
      

      结果:

      0x8e19008

      0x8e19008

      ** 检测到 glibc ** ./a.out: double free or corruption (fasttop): 0x08e19008 *

      如您所见,地址保持不变,但第二次删除以运行时错误结束。行为可能在细节上取决于环境,但作为一般规则,它不会起作用。

      【讨论】:

      • 最后一句话不一定是真的:一些编译器会“保护”你不这样做,所以它可能看起来“工作”。但这仍然是未定义的行为,而且仍然是个坏主意。测试它不是在这里得到答案的正确方法。
      • @Code Gray:这不是测试,而是演示。第一句话不一定是真的,这就是为什么我说“可能取决于环境”。
      【解决方案4】:

      在已删除的内存上调用 delete 将导致未定义的行为。通常,您的程序会崩溃。

      删除 x 后,它将指向的位置是“编译器相关”。在调用 delete 之前,大多数编译器只会让它指向它所在的位置。但是那个内存地址不再有效,因此不应该被调用。

      出于同样的原因,如果需要,必须非常明智和谨慎地使用“删除这个”。 :-)

      【讨论】:

      • 当你说:calling delete on already deleted memory will cause undefined behaviour.。被删除的不是pointer而不是memory吗?谢谢
      • @user:两者都没有被删除,本身。内存正在被释放,这意味着你的程序告诉操作系统:“好的,谢谢你的内存块,我用完了!”并且您的程序不再具有对其的读/写访问权限。
      【解决方案5】:

      它将调用未定义的行为。如果你不做x=NULL,那么x 将指向一个无效的内存位置,如果你尝试使用它会导致未定义的行为。

      【讨论】:

      • 但是,当我执行delete 时,我不是在删除pointer 本身吗?你说“如果你不做 x=NULL 那么 x 将指向一个无效的内存位置”是怎么回事?谢谢
      • @user588855:假设x 在删除之前是 0x11111111。因此,当您执行delete x; 时,此内存位置是空闲的。但是由于您没有将x 设置为NULL,它仍然具有值0x11111111,这是一个已释放的内存位置。尝试使用*xx-&gt; 读取/写入此位置将调用未定义的行为。
      【解决方案6】:

      delete 之后,指针通常仍包含(现在空闲)内存的地址。第二个delete 给出了未定义的行为,所以不要这样做。

      【讨论】:

        猜你喜欢
        • 2013-12-27
        • 2014-01-19
        • 1970-01-01
        • 1970-01-01
        • 2021-08-24
        • 2017-05-08
        • 1970-01-01
        • 2016-05-23
        • 1970-01-01
        相关资源
        最近更新 更多