【发布时间】:2014-04-06 11:33:19
【问题描述】:
C++ 标准为 unclear1 行为提供了大量的定义,这意味着或多或少相同,但存在细微差别。阅读this answer,我注意到措辞“程序格式错误;不需要诊断”。
实现定义与未指定行为的不同之处在于,前一种情况下的实现必须清楚地记录它正在做什么(在后一种情况下,它不需要),两者都是格式良好的。 未定义行为与未指定行为的不同之处在于程序是错误 (1.3.13)。
否则,它们都有一个共同点,即该标准对实施将做什么没有任何假设或要求。
除了 1.4/8,它指出实现可能有扩展,这些扩展不会改变格式良好的程序的行为,但根据标准是格式错误的,并且实现必须诊断这些的使用,但之后可以继续编译和执行格式错误的程序。
格式不正确的程序仅被定义为格式不正确(太棒了!)。另一方面,格式良好的程序被定义为符合语法和可诊断语义规则的程序。因此,这意味着格式错误的程序是违反语法或语义规则(或两者)的程序。换句话说,一个格式错误的程序实际上根本不应该编译(如何以任何有意义的方式翻译一个语法错误的程序?)。
我倾向于认为 erroneous 这个词也意味着编译器应该使用错误消息中止构建(毕竟,erroneous 表明存在错误) ,但 1.3.13 中的“注意”部分明确允许一些不同的东西,包括默默地忽略问题(编译器明显不会因为 UB 而破坏构建,大多数默认情况下甚至不会发出警告) .
人们可能会进一步认为 erroneous 和 ill-formed 是相同的,但如果是这种情况或该词的含义,该标准并未详细说明。
此外,1.4 规定
符合规范的实现应 [...] 接受并正确执行格式良好的程序
和
如果一个程序违反了不需要诊断的规则,[...] 对该程序的实施没有要求。
换句话说,一个符合规范的实现必须接受一个格式良好的程序,但它也可能接受一个格式错误的程序,甚至没有警告。除非,如果程序格式不正确因为它使用了扩展。
第二段暗示任何与“不需要诊断”相关的东西意味着规范中没有要求,这意味着它几乎等同于“未定义的行为”,除了没有提及错误 em>。
因此,使用诸如“格式错误;无需诊断”之类的措辞背后的意图是什么?
“无诊断”的存在表明它与未定义的行为相同(或大部分相同?)。此外,由于实现定义和未指定行为被定义为格式良好,它必须是不同的。
另一方面,由于格式错误的程序破坏了语法/语义规则,它实际上不应该编译。然而,与“不需要诊断”结合使用意味着编译器将被允许在没有警告的情况下静默退出,并且之后您将无法找到可执行文件。
“格式错误;无需诊断”和“未定义行为”之间是否有区别,或者这只是同一事物的复杂同义词?
1对于集体行为缺乏更好的措辞
【问题讨论】:
-
另见question 侧边栏中列出的有用信息。
-
@vonbrand:排名最高的答案似乎得出这样的结论,即“格式错误”意味着“诊断消息加上未定义的行为”,其推理与我的问题相同,即 1.4.2 的措辞与 1.3 相似.13(但这真的意味着它是一样的吗?)。如果我们假设这个推理是正确的,那么“格式错误;没有诊断”将是“诊断加上未定义的行为减去诊断”,所以简单地说是“未定义的行为”。
-
具有讽刺意味的是,我刚刚意识到我链接到的问题中的那个例子(包含让我想知道的引用的那个)必须必然破坏构建: “如果不存在函数参数值,使得函数调用替换会产生一个常量表达式”。如果您需要一个编译时常量(例如,对于模板参数)并且您无法从输入中生成一个,那么除了立即因错误而中止之外,您还能做什么?当然,“无需诊断”不能真正适用于这种情况。
-
没有。 Doing
char *p = malloc(100); free(p); *p = 10;是未定义的行为。包含这些行的程序可以是格式良好的,特别是如果某些其他约束不允许确切的事件序列。似乎唯一明确的不规范的情况来自“单一定义”规则。 -
“符合标准的实现必须接受格式良好的程序”,直至其实现“限制”。所以这是一个非常弱的“必须”。实现应该具有至少与标准中指定的一样大的限制,但这不是严格要求。
标签: c++ language-lawyer undefined-behavior