【问题标题】:Documentation of "invalid pointer value" conversion in C++ implementationsC++ 实现中“无效指针值”转换的文档
【发布时间】:2016-01-28 12:03:20
【问题描述】:

根据 C++ 标准,每个实现都必须记录“实现定义的行为”:

1.3.11 [defns.impl.defined] 实现定义的行为

行为,对于格式良好的程序构造和正确的数据,取决于实现和每个实现文档

并且读取无效的指针值具有实现定义的行为(参见 4.1 左值到右值的转换[conv.lval]):

如果 glvalue 所指的对象包含无效的指针值(3.7.4.2、3.7.4.3),则行为是实现定义的。

(引自草案 n4527,但措辞是“通过无效指针值间接并将无效指针值传递给解除分配函数具有未定义的行为。无效指针值的任何其他使用都具有实现定义的行为。”已在 3.7.4.2 重新分配函数 [basic.stc.dynamic.deallocation] 至少草稿 n3485)

但是,许多流行的实现并没有定义这种行为,许多专家将其描述为“未定义的行为”。

遗漏明确文档的一个可能原因是,据我所知,在附录后面的标准草案中出现的“实现定义的行为索引”中缺少对“无效指针值”的评估。

这是标准中的缺陷吗?自 C++14 以来是否有任何公开的缺陷报告或委员会采取的行动?

【问题讨论】:

  • 在我看来,实现需要定义的部分是 - 一些实现可能会定义复制无效指针值会导致系统生成的运行时错误。(§ 下的脚注3.7.4.3)。您应该能够从处理器的文档中确定加载到某个地址寄存器中的特定位模式是否会导致故障。
  • 所以你的问题是为什么这没有记录在实现定义的行为索引中?
  • @Praetorian:C++ 程序的行为肯定与 CPU 供应商记录的行为不同(考虑一个仅在有符号整数回绕时终止的循环条件——CPU 很可能会定义回绕发生,但 C++ 优化器完全有权将其视为无限循环)
  • @ShafikYaghmour:基本上,是的。它可能不存在,因为它实际上是未定义的行为,而其他部分有错字。或者也许已经有一个委员会尚未投票的建议改写。或者它可能在索引中,使用我不认为相关的措辞。这些是我正在努力学习的类型。
  • 我一直觉得“实现定义的行为”是一个奇怪的概念,因为它只限制编译器文档作者,而不是程序员或编译器作者。 (要么您是可移植地编码,在这种情况下,必须同样避免“实现定义”和“未定义”行为;或者您正在为特定平台编码,在这种情况下,您只关心编译器的保证和规范的区别无关紧要。)

标签: c++ pointers language-lawyer


【解决方案1】:

CWG #1438 更改了有关无效指针值的语义:

当前标准规定任何使用无效指针值的行为 产生未定义的行为(3.7.4.2 [basic.stc.dynamic.deallocation] 第 4 段)。这不仅包括取消引用指针,还包括 甚至只是获取它的价值。这种严厉的原因 限制是过去的一些架构使用专用的 用于指针加载和存储的地址寄存器,它们可能会出错 例如,如果指针中的段号当前不是 映射。

尚不清楚此类限制是否有必要 当前使用或合理预见的架构。这应该是 调查是否可以放宽限制以仅适用 解除对指针的引用。

[conv.lval]的变化是CWG #616的分辨率,基本上采用了上面的。
将其从 UB 提升到实现定义的行为是有意的,所以我认为索引中没有这一段是疏忽。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多