【问题标题】:Dereference null is not always UB?取消引用 null 并不总是 UB?
【发布时间】:2023-03-04 09:00:01
【问题描述】:

我一直知道标准要求取消引用 null 是 UB。然而,

(Link 1)

p = 0; *p;本质上不是错误。

并提供指向

的链接

(Link 2)

当 p 为 null 时,*p 不是错误,除非将左值转换为左值

(我认为这是一个错字,可能应该是 lvalue is convert to an rvalue

链接1也说

字符* p = 0;字符 *q = &*(p)

是“未定义”,我只能将其理解为定义明确的或至少实现定义的

语言律师能否对正在发生的事情提供权威解释?

【问题讨论】:

  • 我不是语言律师,但我对链接的阅读是,在本身 UB 中取消引用空指针,仅使用值。是的,这似乎是一个错字,应该是左值到右值,因为这就是它在链接 1 中的引用方式。我认为这在静态成员的情况下是有意义的,因为只需要 operator* 的静态类型,并且据我所见,link1 与此一致。
  • 如果实现造成段错误,那真的是 UB 吗?我想不出有什么不一样的。

标签: c++ language-lawyer undefined-behavior


【解决方案1】:

我在this answer 中通过空指针探讨了间接主题。简而言之,它本身确实是明确定义的,正如您在引用的核心问题中所阐述的那样。委员会使用了多年前提出的空左值概念(但从未采用); *p 应该是这样一个空左值,除非我们尝试访问该左值后面的(不存在的)内存位置(例如,通过执行左值到右值的转换),否则所有其他操作都按预期运行.例如。 &*p 等价于 p,除非 p 无效。 (这也适用于数组末尾的指针,这是常见的习惯用法&arr[n] 所必需的)。

我还开始起草paper for empty lvalues(这是 WIP,针对 N4640 的 rebase 尚未完成),所以我们有机会在稍后阶段看到更多。

【讨论】:

  • 恕我直言,如果 C 和 C++ 标准中的许多问题认识到零大小左值的概念,并且将 null 视为这样一个实体,则可以清理它们。如果一个人认识到指针可以指向一个对象的开始和/或结束[所以给定int foo[10],指针foo+1将指向第一项的结束和第二项的开始,而foo+10将只指向到第十项的末尾],并且指向不同对象的指针必须是不同的除了指向一个对象开头的指针可能指向另一个对象的结尾...
  • ...那么“最后一个元素加一个”概念将自然地适用于其他所有内容,无需特殊处理,空左值也同样适用(起始地址可能等于其他一些的结束地址对象,并且结束地址可以等于另一个对象的开始)。要求需要具有唯一地址的对象的代码必须要么给它们非零大小,要么使用创建唯一对象的特殊方法比要求所有对象都具有非零大小要干净得多。
猜你喜欢
  • 1970-01-01
  • 2017-01-29
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多