未定义行为与错误形成之间的区别,无需诊断消息

时间:2014-03-04 18:45:14

标签: c++ language-lawyer undefined-behavior

C ++标准为不清楚 1 行为提供了大量定义,这些定义或多或少与微妙差异相同。阅读this answer,我注意到“程序格式错误;无需诊断”

实施定义的未指定的行为的不同之处在于,前一种情况下的实施必须清楚地记录它正在做的事情(在后一种情况下,它不需要),两者都格式良好未定义行为与未指定的行为不同,因为程序错误(1.3.13)。
否则它们都有一个共同点,就是标准不会对实现的内容做出任何假设或要求。 除1.4 / 8之外,其中声明实现可能具有不会改变格式良好的程序的行为的扩展,但根据标准是不正确的,并且实现必须诊断使用这些,但之后可以继续编译和执行不正确的程序。

格式错误的程序只是被定义为格式不正确(太棒了!)。另一方面,格式良好的程序被定义为遵循语法和可诊断语义规则的程序。因此,这意味着错误的程序是打破语法或语义规则(或两者)的程序。换句话说,一个格式不正确的程序实际上根本不应该编译(如何以任何有意义的方式翻译例如语法错误的程序?)。

我倾向于认为错误这个词也意味着编译器应该使用错误消息中止构建(毕竟,错误表示存在错误) ,但1.3.13中的“注意”部分明确允许一些不同的东西,包括默默地忽略问题(并且编译器显然因为UB而破坏构建,大多数甚至没有默认警告)

有人可能会进一步认为错误的和格式错误是相同的,但如果是这种情况或该词应该是什么意思,标准就不会详细说明。

此外,1.4表示

  

符合要求的实施应[...]接受并正确执行格式良好的程序

  

如果某个程序违反了不需要诊断的规则,则对该程序的实施没有要求。

换句话说,符合要求的实施必须接受格式良好的程序,但它也可能接受形式错误的程序,甚至没有警告。除非,如果程序格式错误,因为它使用扩展名

第二段建议任何与“无需诊断”相关的内容意味着规范中没有要求,这意味着它大部分等同于“未定义的行为”,除了没有提到错误

因此使用“格式错误;无需诊断”

等措辞背后的意图是什么?

“无诊断”的存在表明它与未定义的行为完全相同(或大多数相同?)。此外,由于实现定义的未指定的行为被定义为格式良好的,因此它必须是不同的

另一方面,由于格式错误的程序会破坏语法/语义规则,因此它实际上不应该编译。然而,与“不需要诊断”相结合意味着允许编译器在没有警告的情况下以静默方式退出,并且之后您将无法找到可执行文件。

“形成不良;无需诊断”和“未定义行为”之间是否有区别,或者这只是同一事物的复杂同义词?

<小时/> 1 缺乏对行为集合的更好措辞

2 个答案:

答案 0 :(得分:13)

标准并不总是像我们想的那样连贯,因为 它是一个非常大的文档,由一个数字写成(在实践中) 不同的人,尽管所有的证据阅读 确实发生了,不一致的地方漏掉了。如果是 未定义的行为(和一般的错误),我认为有一个 对于大多数最基本的事情来说,还有其他问题 (指针等),C ++标准来自C。但是 C标准认为所有错误都是未定义的 行为,除非另有说明,否则作为C ++标准 试图从所有错误需要的角度来看 除非另有说明,否则为诊断。 (虽然他们还在 必须考虑标准省略指定的情况 一种行为。)我认为这占了很多 措辞不一致。

在全球范围内,这种不一致是令人遗憾的,但总的来说,如果 标准说某些东西是错误的,或者形象不对, 然后它需要诊断,除非标准说它 没有,或者它是未定义的行为。在类似的东西 “格式错误;无需诊断”,“无诊断 必要的“很重要,因为否则,它需要 诊断。至于“形成不良;没有 诊断需要“和”未定义的行为“,没有任何。 在代码的情况下,第一个可能更频繁 不正确,第二个是运行时问题,但事实并非如此 系统性。 (一个定义的规范 规则 - 明确编译时间问题 - 结束于“然后 行为未定义“。)

答案 1 :(得分:7)

它应该是这样的:只要特定的程序运行不触发未定义的行为,未定义的东西不会引起问题。例如。空指针取消引用只会破坏您的特定程序运行时的日期(以其输入为特征:I / O,非确定性函数,如时钟查询等)实际上会执行它 - 但它会向后移动,因此它可能会出现未定义的行为甚至在技术上达到取消引用之前。 (这主要是为了允许我认为代码重新排列。)

虽然不正确的NDR是实现在翻译期间诊断的东西,但可能由于各种技术或理论限制而无法实现。例如。 ODR要求实施收集实体的所有定义并进行比较;但这是一个巨大的资源消耗。一些NDR的东西甚至在计算上是不可行的。当实现没有立即诊断出这些东西时,会出现未定义的行为。

实际上,未定义的行为适用于非运行时条件的一些奇怪的情况。一些奇怪的预处理器问题会触发未定义的行为。这些都很奇怪,因为它们在编译的程序中没有有意义的表示,因此不清楚是什么导致它们执行。

尽管如此,这个观点仍然让你有理由知道为什么有两个术语。