C++实现中“无效指针值”转换的文档记录

14
根据C++标准,每个实现都必须记录“实现定义的行为”:
1.3.11 [defns.impl.defined] 实现定义的行为 对于良好形成的程序结构和正确的数据,取决于实现并且每个实现都有文档记录的行为。
阅读无效指针值具有实现定义的行为(参见4.1 Lvalue-to-rvalue conversion [conv.lval]):
如果glvalue引用的对象包含无效指针值(3.7.4.2、3.7.4.3),则行为是实现定义的。
然而,许多流行的实现不定义此行为,并且许多专家将其描述为“未定义的行为”。
明确文档遗漏的一个可能原因是,在附录后出现的“实现定义的行为索引”中缺少对“无效指针值”的评估。
这是否是标准中的缺陷?自C++14以来,是否有任何未解决的问题或委员会行动?

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

9

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

当前标准规定,任何使用无效指针值都会产生未定义行为(3.7.4.2 [basic.stc.dynamic.deallocation] 第4段)。这不仅包括对指针进行解引用,甚至只是获取其值也是如此。实行如此严格的限制的原因是过去一些架构在指针加载和存储时使用专用的地址寄存器,如果指针中的段号当前未映射,那么它们可能会导致故障。

目前使用或合理预见的架构是否需要这样的限制尚不清楚。应该调查一下,看看是否可以放松限制,只适用于对指针进行解引用。

[conv.lval]中的更改是解决CWG #616的结果,其基本上采纳了上述内容。
将其从未定义行为提升为实现定义行为是有意的,因此我认为索引中没有该段落是一种疏忽。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接