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

delete[] with different type undefined behaviour?

本文关键字:未定义 同类型 删除      更新时间:2023-10-16

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

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

在标准中 有

否则,行为未定义。在第二种备选方案(删除数组(中,删除的操作数的值可以是空指针值,也可以是前一个数组 new-expression 产生的指针值。79 否则,行为是未定义的。[ 注意:这意味着删除表达式的语法必须与 new 分配的对象类型匹配,而不是与 new 表达式的语法匹配。 — 尾注 ]

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

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

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

是的,行为是未定义的。

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

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

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

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,类型确实必须完全匹配,而不仅仅是名称。

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

特别是:

struct Base { virtual ~Base() = default; };
struct Derived: Base { int a; };
int main() {
Base* p = new Derived[5];
delete[] p;
}

也是未定义的行为。


@Justin 在评论中提供了相关的标准报价,请参阅此处:

5.3.5 [删除]

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

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