【问题标题】:Is it legal to call delete on a null pointer of an incomplete type?在不完整类型的空指针上调用 delete 是否合法?
【发布时间】:2018-05-01 09:50:57
【问题描述】:

如果是这样,为什么下面的代码会给我警告

注意:无论是析构函数还是类特定操作符 delete 都不会被调用,即使它们是在定义类时声明的

?

struct C;

int main()
{
    C *c = nullptr;

    delete c;

    return 0;
}

理解如果C 具有非平凡/虚拟析构函数,但不是标准保证/定义,为什么它可能在一般情况下是未定义的行为无论情况如何,nullptr 上的 delete 始终是 noop

重申一下:我专门询问指向不完整类型的指针是nullptr

【问题讨论】:

  • 事实上,编译器给你一个警告并不意味着代码是错误的。例如未使用的变量。这通常意味着代码不安全。
  • 对我来说这个问题没有多大意义。要么,您计划 c 始终为 NULL,那么您根本不需要 delete 行,或者您最终允许稍后为其分配一些值,在这种情况下您需要完整的类型定义...
  • @Fang 我的问题是针对不完整类型的。
  • @Slava 很好,是的。这就是为什么我决定要求确定。至少这种情况对于编译器来说似乎很容易弄清楚并且不发出警告(但话又说回来,他们可能只是懒得实现这种极端情况)。
  • 好吧,C *c = nullptr; delete c; 无论如何都不应该存在,因为它什么都不做,编译器确实能够检测到这一点并对其进行优化。但是这样的代码表明你的代码有问题,在编译器中实现这种特殊情况是不值得的。

标签: c++ language-lawyer delete-operator incomplete-type nullptr


【解决方案1】:

标准说 ([expr.delete]/5):

如果要删除的对象在删除点具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为未定义。

所以如果T 有一个非平凡的析构函数或有一个operator delete 重载,你就会得到UB。关于 UB 基于指针的(即:它是否为空指针)没有任何说明。


关于“对象被删除”是什么意思?

可以认为“正在删除的对象”意味着该子句仅适用于对实际对象的delete 调用。因此,如果你传递一个空指针,它就不适用。

首先,关于delete 行为的标准讨论的其余部分明确指出其行为不适用于空指针。 [expr.delete]/6&7 都以“如果删除表达式的操作数的值不是空指针值”开头。第 5 段明确不包含这些词。因此,我们必须假设它确实适用于空指针。

其次,如果传递一个空指针,“对象被删除”的含义是什么?毕竟那里没有“对象”。

好吧,考虑一下如果“正在删除的对象”专门讨论该指针末尾的对象,那么解释此文本意味着什么。那么,如果您要删除具有非平凡析构函数的不完整类数组会发生什么?

按照这种逻辑,无论指针是否为空,此子句都不适用。为什么?因为“被删除的对象”是 array 类型,而不是类类型。因此,该条款不能适用。这意味着编译器必须能够在不完整的类数组上调用delete[]

但这不可能实施;这将要求编译器能够追踪尚不存在的代码。

因此,要么“正在删除的对象”打算引用std::remove_pointer_t<std::decay_t<decltype(expr)>>,要么标准要求无法实现的行为。标准措辞可能会稍微清理一下,将“如果正在删除的对象在删除点具有不完整的类类型”替换为“如果T 是指向U 的指针或U 的数组,并且U 在删除点的类类型不完整,..."

【讨论】:

  • 但是如果指针的值为 null 则没有对象。所以这不适用。
  • @rex 从技术角度来看,该标准声明为 UB 的许多事情似乎都是直接定义的行为。 ((Foo*)nullptr)->someStaticVariable 例如。没有一个正常思维的编译器实际上会发出代码来取消引用这里的空指针。尽管如此,声明是UB。而且它被声明为 UB 的事实意味着您必须期望某些(未来的)编译器会丢弃您的 UB 调用代码作为优化。
  • 如果对象的生命周期没有开始,它是一个对象吗?我在这里可能错了,我看到标准的其余部分确实将“空指针值”作为其余语句中的特定限定符。最后看来UB的决定因素不是指针的值,而是delete操作符有没有关系。
  • “被删除的对象”指的是什么? delete 语句本身的操作数,还是delete 语句的操作数指向的对象? (真正的问题,我没有标准。)如果是前者,这个答案是有道理的。如果是后者,操作数为空指针,“被删除的对象”缺少所指对象,很像“法国现任国王”,该语句根本不适用。在这种情况下,“它会为空指针做出规定”是无关紧要的;隐含地,它确实,因为空指针从不指向对象。
  • 请记住,总是有第 3 个选项:该标准在这里存在缺陷,其字面意思并没有准确地传达其意图。完全不会是第一次。我声称只要有理智的人可以开始有说服力地争论哪种解释是最好的,情况就是如此。 :-P
猜你喜欢
  • 1970-01-01
  • 2016-12-07
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2012-08-15
  • 2013-03-11
相关资源
最近更新 更多