为什么删除void *是UB而不是编译错误?

时间:2018-06-13 17:33:44

标签: c++ language-lawyer undefined-behavior delete-operator void-pointers

为什么通过void*删除对象是未定义的行为,而不是编译错误?

void foo(void* p) {
    delete p;
}

此代码编译并生成代码,尽管gcc和clang上有警告(令人惊讶的是,ICC没有发出警告):

  

:2:5:警告:无法使用指向''''的指针删除表达式   输入'void *'[-Wdelete-incomplete]

为什么不是简单的格式错误的程序语法无效?看起来标准不会花费太多时间,在[expr.delete]中说

  

这意味着无法使用类型指针删除对象   void *因为void不是对象类型。

我有什么理由不知道为什么这不会触发硬编译错误?

1 个答案:

答案 0 :(得分:15)

在现代C ++中删除void *指针 格式错误(即我们通常称之为"编译错误")

  

8.3.5删除
   1 [...]操作数应为指向对象类型或类类型的指针。

void *不是指向对象类型的指针。

在C ++ 98中,情况有所不同。删除void *类型的空指针是NOP,而删除void *类型的非空指针是UB。

规范中的此更改似乎是由defect report #599触发的。原始规范允许在delete-expression中提供任何指针类型的空指针,例如函数指针。这看起来不必要地宽容。 DR#599的解决方案收紧了要求,也禁止了void *