繁体   English   中英

如果没有发生左值到右值的转换,取消引用无效指针是否合法

[英]Is dereferencing invalid pointers legal if no lvalue-to-rvalue conversion occurs

尽我所能,我见过的最接近的答案是this ,有两个完全相反的答案(!)

问题很简单,这合法吗?

auto p = reinterpret_cast<int*>(0xbadface);
*p;  // legal?

我对此事的看法

  1. 将整数转换为指针:对可以转换的内容没有限制
  2. 间接:仅说明结果是左值。
  3. Lifetimes :只说明不能对对象做的事情,这里没有对象
  4. 表达式语句*p是丢弃值表达式
  5. 丢弃的值表达式:不发生左值到右值的转换
  6. 左值未定义:又名严格别名规则,仅当左值转换为右值时

所以我得出结论,没有明确说这是未定义的行为。 然而,我清楚地记得有些平台会因无效指针而陷入间接寻址。 我的推理出了什么问题?

[basic.compound]说:

指针类型的每个值都是以下之一:

  • 指向对象或函数的指针(该指针被称为指向该对象或函数),或
  • 超过对象末尾的指针 ([expr.add]),或
  • 该类型的空指针值 ([conv.ptr]),或
  • 无效的指针值。

通过消元过程我们可以推断出p是一个无效的指针值。

[basic.stc]说:

通过无效指针值间接传递和将无效指针值传递给解除分配函数具有未定义的行为 无效指针值的任何其他使用都具有实现定义的行为。

据说间接运算符通过[expr.unary.op]执行间接,我想说的是,无论是否使用结果,表达式*p都会导致 UB。

...某些平台会因无效指针而陷入间接寻址。

大多数平台会捕获无效地址访问 这与这个问题没有任何矛盾。 *p;发生了什么的问题*p; 归结为是否尝试在无效地址处实际获取

获取问题与核心问题232 (通过空指针间接)非常相似。 正如您已经指出的那样, *p; 是一个丢弃的值表达式,因此不会发生左值到右值的转换(“获取”):

汤姆梅:

...只有“获取”的行为,左值到右值的转换,才会触发格式错误或未定义的行为。

随后:

2003 年 10 月会议记录:

我们同意标准中的方法似乎没问题: p = 0; *p; p = 0; *p; 本质上不是错误。 左值到右值的转换会赋予它未定义的行为。


至于reinterpret_cast<int*>(0xbadface)产生一个有效的指针,实际上在具有严格指针安全的实现中,它不会是一个安全派生的指针,因此是无效的,任何使用它都是 UB。

但是在宽松的指针安全性的情况下,结果指针是有效的(否则就不可能使用从以 C 或其他语言编写的二进制库和组件返回的指针)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM