“无需诊断”的理由是什么?

时间:2014-07-22 07:53:36

标签: c++ c++11 language-lawyer

大多数人都熟悉" undefined"和"未指明" C ++中的行为记录,但是"不需要诊断"?

我注意this question and answer,处理不良形成的程序,但没有详细说明"根本不需要诊断"语句。

委员会在将某些内容归类为&#34时所采用的一般方法是什么?不需要诊断"?

  • 标准委员会指定错误的错误有多严重?
  • 这些错误是否几乎不可能被发现,因此诊断?

" undefined"的例子和"未指明"行为不是短缺的;在没有ODR的情况下,有什么实际的例子可以用于"不需要诊断"输入错误?

2 个答案:

答案 0 :(得分:12)

这里有一个讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/lk1qAvCiviY由各委员会成员发言。

普遍的共识似乎是

  • 没有规范性差异
  • 形成不良;无需诊断仅用于编译时规则违规,从不用于运行时规则违规。

正如我在那个帖子中所说,我曾经在一次讨论中听过(我不记得在哪一个,但我确信有很多有见地的委员会成员参与)

  • 形成不良;对于明显违反规则规则并且原则上可以在编译时进行诊断的情况,无需诊断,但需要从实施中付出巨大努力。
  • 未定义的行为对于实现可以找到有用含义的东西,所以不一定是纯粹的邪恶,并且对于任何导致任意后果的运行时违规。

对我来说粗略的指南是;如果它在编译时,它往往是“格式错误;不需要诊断”,如果它在运行时,它总是“未定义的行为”。

答案 1 :(得分:11)

我会尝试解释"不需要诊断" 分类为未定义行为(UB)的行为

标准通过说&#34; UB不需要诊断&#34; 1 ,使编译器完全自由地优化代码,因为编译器只能通过<消除许多开销em>假设你的程序是完全明确的(这意味着你的程序没有UB),这是一个良好的假设 - 毕竟如果这个假设是错误的,那么任何东西基于这个(错误的)假设的编译器会以一种未定义的(即不可预测的)方式运行,这种方式完全一致,因为你的程序还有未定义的行为!

请注意,包含UB的程序可以像任何行为一样自由。再次注意我说&#34;一致&#34;因为它与标准的立场是一致的:&#34;如果语言规范和编译器包含UB(s)&#34;

1。 相反的是&#34;需要诊断&#34;这意味着编译器必需通过发出警告错误消息向程序员提供诊断。换句话说,允许假设程序定义明确,以优化代码的某些部分

这是一篇文章(在LLVM博客上),它使用示例进一步解释了这一点:

除了文章( italicised mine )之外:

  

有符号整数溢出:如果对&#39; int&#39;进行算术运算类型(例如)   溢出,结果未定义。一个例子是&#34; INT_MAX + 1&#34;是   不保证是INT_MIN。 此行为启用某些类   对某些代码很重要的优化。例如,知道   INT_MAX + 1未定义允许优化&#34; X + 1&gt; X&#34; to&#34; true&#34;。   知道乘法&#34;不能&#34;溢出(因为这样做会   未定义)允许优化&#34; X * 2/2&#34;到&#34; X&#34; 。虽然看起来很像   琐碎的,这些东西通常都是通过内联和内联来暴露的   宏观扩张。这允许的更重要的优化是   &#34;&LT; =&#34;像这样的循环:

for (i = 0; i <= N; ++i) { ... }
     

在此循环中,编译器可以假定循环将迭代   如果&#34; i&#34;正好是N + 1次溢出时未定义,允许a   广泛的循环优化可以启动。另一方面,如果   变量被定义为在溢出时回绕,然后是编译器   必须假设循环可能是无限的(如果N是,则会发生   INT_MAX) - 然后禁用这些重要的循环优化。   由于代码使用太多,这尤其会影响64位平台   &#34; INT&#34;作为诱导变量。

     

值得注意的是,保证定义无符号溢出   作为2的补充(包装)溢出,所以你总是可以使用它们。该   制定有符号整数溢出的成本就是这些   简单地丢失优化(例如,常见的症状是吨   64位目标上循环内的符号扩展名)。 Clang和   海湾合作委员会接受&#34; -fwrapv&#34;标志强制编译器处理   定义的有符号整数溢出(除了INT_MIN除以之外)   -1)。

我建议你阅读整篇文章 - 它有三个部分,一切都很好。

希望有所帮助。