【问题标题】:Is performing indirection from a pointer acquired from converting an integer value definitely UB?从转换整数值获得的指针执行间接绝对是UB吗?
【发布时间】:2022-01-20 20:03:48
【问题描述】:

考虑这个例子

int main(){
  std::intptr_­t value = /* a special integer value */; 
  int* ptr = reinterpret_­cast<int*>(value ); // #1
  int v = *ptr;  // #2
}

[expr.reinterpret.cast] p5 说

整数类型或枚举类型的值可以显式转换为指针。转换为足够大小的整数(如果实现中存在这样的整数)并返回相同指针类型的指针将具有其原始值; 指针和整数之间的映射是由实现定义的

至少,步骤#1 是实现定义的。对于步骤#2,我认为有四种可能,分别是

  1. 实现不支持这种转换,实现会为它做任何事情。
  2. 指针值正好是int类型对象的地址,结果格式正确。
  3. 指针值为int类型以外的对象地址,结果为UB。
  4. 指针值是无效的指针值,间接是UB。

这意味着通过指针ptr 的间接行为将取决于实现。如果实现采用选项2,则不一定是UB。所以,我想知道这个案子是不是肯定是UB还是肯定是UB?如果是后者,哪些条款强烈说明了该行为?

【问题讨论】:

  • 我认为关键问题是 - *ptr 是否取消引用在程序生命周期内创建的 int object?如果没有,那么我们有 UB。
  • 从标准的角度来看,是的,这是未定义的行为。可以将指针映射到整数值,然后将该整数值包映射到指针 - 但映射(在任一方向)是实现定义的。除其他外,这可能意味着往返映射(例如,指向整数值的指针到指针)可能不会给出原始值。更一般地说,从整数值到指针的映射是否给出指向对象的有效指针是实现定义的。如果指针未指向有效对象,则取消引用它会产生未定义的行为。
  • @Peter 从标准的角度来看,我不认为它绝对是 UB。此外,往返映射绝对是格式良好的,因为标准保证了这一点。
  • @xmh0511 您对标准的要求和实现的功能感到困惑。在很多情况下,实现选择可靠地产生特定行为,其中行为仍未由标准定义(即没有实现提供标准是否未定义某事的标准)。在往返行为上,该标准为某些整数类型(例如std::ptrdiff_tstd::size_t)提供了相关保证,但这些类型本身是实现定义的。其他整数类型当然没有这样的保证,比如int
  • @Peter 我认为您对“UB”的看法与我的不同。我在问这个案子是否肯定是“UB”。实现定义的行为与“未定义的行为”无关,它们不是一回事。您应该指出 #2 是 UB 还是实现定义的行为。如果肯定是UB,请在此处引用相关报价。我会很感激的。

标签: c++ language-lawyer


【解决方案1】:

标准没有什么比你引用的更多的了。如果整数值取自指针到整数的转换,则该标准仅保证整数到指针转换的含义。所有其他整数到指针转换的含义由实现定义。

这意味着关于它们的一切都是“实现定义的”:它们会产生什么结果以及使用这些结果会做什么。毕竟,指针到整数到指针的往返说明你得到了“原始值”。结果指针具有“原始值”这一事实意味着它的行为与您复制原始指针本身的行为完全相同。所以这个标准不需要多说什么了。

从实现定义的整数到指针转换中获取的指针的行为是......实现定义的。如果一个实现说支持这种转换,它必须说明支持的转换的结果是什么。也就是说,如果实现支持将某个“特殊整数值”转换为int*,则它必须说明该转换的结果是什么。这包括它是否指向实际的 int 或其他内容。

【讨论】:

  • 那么,你同意这个案子不是确定的UB吗?它可能是UB,也可能不是UB,这取决于执行情况如何处理?正如我所做的分析。
【解决方案2】:

从转换整数值获得的指针执行间接操作肯定是UB吗?

并非总是如此。这是一个绝对不是UB的例子:

int i = 42;
std::intptr_t value = reinterpret_cast<std::intptr_t>(&i); 
int* ptr = reinterpret_cast<int*>(value);
int v = *ptr;

这是因为将指针转换为足够大小的整数并返回到相同的指针类型可以保证产生与您引用的规则中所述相同的指针值。由于原始指针值对间接有效,因此转换后的值也是有效的。

【讨论】:

    猜你喜欢
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 2022-01-25
    相关资源
    最近更新 更多