如果您将delete[]应用于非数组指针,会发生什么?

4
如果在C++中将“delete”应用于数组而不是“delete []”,那么将会创建内存泄漏,因为只有第一个元素被删除。但是,如果您意外地将“delete []”应用于非数组指针会发生什么呢?例如(仅作为玩具示例):
   class X {   
      void  foo()
      {
          X* x = new X();
          delete[] x; // What happens here?
      }
   };

它会有什么危害吗?如果有,那么是哪些危害?

13
未定义行为是未定义的。 - Jonathan Potter
1
是的,它可能会造成伤害。它可以做任何事情。 - Jonathan Leffler
1
你的鼻子可能会飞出恶魔。 - πάντα ῥεῖ
1
这个程序到底做什么是未定义的。最好的情况下,这使得该程序无用,但更糟糕的是,它可能会欺骗某人认为这不仅仅是一个无用的程序,并对其产生期望。 - Kerrek SB
可能是How does delete[] know it's an array?的重复问题(请参见第一个答案;“不知道”所暗示的实际原因是UB的原因)。 - user2864740
@Jonathan Potter,请您将您的评论提交为答案,这样我就可以接受它了。非常感谢! - Paul Jansen
2个回答

1
如果在C++中对数组应用"delete"而不是"delete[]",则会创建内存泄漏,因为只有第一个元素被删除。但这并不总是正确的。因为"new"、"new[]"、"delete"、"delete[]"运算符也可以被重载,使用delete而不是delete[](或者反过来)可能会产生很大的差异。此外,一些编译器使用此处描述的超额分配技术。因此,在非数组指针上应用delete[]会导致未定义的行为。

过度分配并不是未定义行为的原因,将delete[]应用于非数组指针本身才是。 - kraskevich
首先,这个问题与重载无关。其次,newdelete类型不匹配是未定义的行为,在实践中会导致几乎所有现有编译器出现实际问题。 - James Kanze

1
如果您在需要delete[]的地方使用简单的delete,则不会出现内存泄漏,而是出现未定义的行为。在许多情况下,您将破坏自由空间竞技场,导致后续程序崩溃,但当然,未定义的行为是未定义的,因此任何事情都可能发生。
在需要简单delete的地方使用delete[]也是未定义的行为;实际上,它也经常会导致破坏自由空间竞技场或其他丑陋的结果。
当然,在实践中,我想不到任何情况下您会使用数组new,因此您几乎可以忘记delete[]

1
即使你使用数组new,也应该在初始化std::unique_ptr<T[]>或类似的智能指针的上下文中使用,这样它会自动调用delete[]来释放内存。 - Ben Voigt
@BenVoigt 或许吧,但是在哪种情况下?std::unique_ptr并不是万能药,通常会像std::vector一样运作。假设你正在分配内存,那么是因为你需要复制它,而复制std::vector太昂贵了。(在这种情况下,std::shared_ptr可能更合适。) - James Kanze
std::vector 被过度使用,因为几十年来它是管理数组的唯一标准智能指针。但是通常情况下,您不需要调整大小或批量复制,在这种情况下,std::unique_ptr<T[]> 更适合此任务。 “假设,如果您正在分配,那是因为您需要复制它”... 不,我发现通常是因为大小在编译时不固定。 - Ben Voigt
@BenVoigt 如果编译时不知道大小,std :: vector 就可以完美工作。 您可能想要不使用它的唯一时间是因为出于性能原因需要浅复制(带有所有问题)。 我看不出何时std :: unique_ptr <T []> 会更合适:您会丢失长度信息,并且无法获取具有边界检查的调试版本。 - James Kanze
考虑存储一个矩阵。行数和列数已经分别存储,因此向量中的长度信息过于冗长(分离大小和容量),多余且无用(因为总长度不能用于验证列或行索引或线性偏移)。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接