删除[]具有不同类型的未定义行为?

Gab*_*iel 17 c++

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

#include <stdint.h>

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

标准中

如果不是,则行为未定义.在第二个替代(删除数组)中,delete的操作数的值可以是空指针值或由前一个数组new-expression 79产生的指针值.如果不是,则行为是未定义的.[注意:这意味着delete-expression的语法必须与new分配的对象的类型匹配,而不是new-expression的语法. - 结束说明]

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

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

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

Bat*_*eba 21

是的,行为未定义.

传递给的指针delete[]必须与您从中获取的指针的类型相同new[].

请注意,对于deletenew,delete允许提交的指针与多态相关.

  • 标准链接说:[\ [expr.delete \]#3](https://timsong-cpp.github.io/cppwp/n3337/expr.delete#3) (4认同)
  • 好吧,在许多平台上,它仍然可能生成合法代码,这就是为什么AS无法检测到它.valgrind可能也不会.问题是在某些情况下,`c`的值与`p`的值不同,或者实现以更有区别的方式跟踪内存分配,这就是C++标准带有UB的地方. (3认同)
  • 有趣.似乎有人发现我现在删除的评论令人反感. (3认同)
  • 我担心你有些错误:`delete []`没有多态的规定.请参阅/sf/answers/3676413961/ (3认同)

MSa*_*ers 5

是的,确实是Undefined Behavior中的代码.短语意味着当你重写它时它仍然是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.
  }
}
Run Code Online (Sandbox Code Playgroud)

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