【问题标题】:delete[] with different type undefined behaviour?delete[] 具有不同类型的未定义行为?
【发布时间】:2018-09-26 07:00:51
【问题描述】:

我想知道这是否是未定义的行为:

#include <stdint.h>

int main() {
  auto* p = new uint8_t[32];
  float* c = reinterpret_cast<float*>(p);
  delete[] c;
}

standard

如果不是,则行为未定义。在第二种选择(删除数组)中,delete 操作数的值可能是空指针值或由先前数组 new-expression 产生的指针值。79 如果不是,则行为未定义。 [ 注意:这意味着 delete-expression 的语法必须与 new 分配的对象的类型匹配,而不是 new-expression 的语法。 ——尾注]

所以解释有点不清楚的短语

这意味着 delete-expression 的语法必须与 new 分配的对象的类型匹配,而不是 new-expression 的语法

我可以说上面是未定义的行为,对吗?

【问题讨论】:

  • 您引用了错误的段落。下一段是说类型必须匹配,否则它是未定义的。
  • 在您的特定情况下,未定义的行为是“无害的”(如果调用 UB 可能是无害的),因此原则上它可以被明确定义。但是想想如果析构函数不是像你的例子那样微不足道会发生什么。在这种情况下编译器应该做什么?它必须调用 some 析构函数,只有哪一个是正确的,以及它如何处理它所指的可能不正确的内存块(实际上是其他类型)?
  • 请注意,您对reinterpret_cast 的使用具有实现定义的行为。在(不相关的)指针类型之间进行转换时,对齐方式可能会有所不同,例如。

标签: c++


【解决方案1】:

是的,行为未定义。

传递给delete[] 的指针必须与您从new[] 返回的指针类型相同。

注意对于deletenew,提交给delete的指针是允许多态关联的。

【讨论】:

  • 标准链接:[expr.delete]#3
  • 好吧,在许多平台上它可能仍会生成合法代码,这就是 AS 无法检测到它的原因。 valgrind 也可能不会。问题是在某些情况下c 的值不会与p 的值相同,或者实现以更区分的方式跟踪内存分配,这就是 C++ 标准与 UB 一起提供的地方。
  • 有趣。似乎有人发现我现在删除的评论令人反感。
  • 恐怕你有一部分是错的:delete[] 没有多态性规定。见stackoverflow.com/a/52520199/147192
  • @MatthieuM.:嗯,你每天都能学到新东西!我已经修改并在维基上找到了答案。
【解决方案2】:

是的,确实是未定义行为中的代码。措辞意味着当您将其重写为时它仍然是 UB

int main() {
  void* p;
  {
     using T = uint8_t;
     p = new T [32];
  }
  {
    using T = float;
    T* c = reinterpret_cast<float*>(p);
    delete[] c; // The behaviour is still undefined.
  }
}

IOW,类型确实必须完全匹配,而不仅仅是名称。

【讨论】:

  • 我希望你不介意我发表评论;以防万一有人快速阅读您的 sn-p 作为解决方案。还有一个赞成票!
【解决方案3】:

如果p 的类型与new[] 返回的类型不同,则调用delete[] p; 是未定义的行为。

值得注意的是:

struct Base { virtual ~Base() = default; };
struct Derived: Base { int a; };

int main() {
    Base* p = new Derived[5];
    delete[] p;
}

也是未定义的行为。


@Justin 在评论see it here 中提供了相关标准引用:

5.3.5 [expr.delete]

(3)在第一种选择(delete object)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为动态对象的基类要删除的对象的类型和静态类型应具有虚拟析构函数或行为未定义。 在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

注意在我强调的 delete array 案例中没有提供多态关系;与删除对象的情况相反。

【讨论】:

    猜你喜欢
    • 2012-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    相关资源
    最近更新 更多