运行从具有"约束违规"的代码生成的二进制文件实际上是未定义的行为吗?

Sou*_*osh 4 c language-lawyer

参考:这个问题

上下文:return结尾处main()没有表达式的语句,如

 return;
Run Code Online (Sandbox Code Playgroud)

当我阅读标准时,它似乎是 未定义的行为,所以我写了一个答案.

然而,另一个答案说,这不是UB.

我在哪里读错或理解标准语言


注意:我已经看过这个帖子,但我不能总结.

Kei*_*son 8

让我们假设这个背景:

int main(void) {
    return;
}
Run Code Online (Sandbox Code Playgroud)

和托管的实现.

请注意,void main()并非严格禁止(允许实现允许它),并且return;在此类定义中完全有效main.

首先,这return;显然是违反约束的行为.它违反了N1570 6.8.6.4p1:

return没有表达式的语句只能出现在返回类型为的函数中void.

(这不是C90中的约束违规;在C99中已经改变了.)

该标准要求编译器为包含违反约束或语法规则的任何程序发出至少一个诊断.一旦完成,它就可以继续生成可执行文件(如果诊断是非致命警告).

目前尚不清楚是否存在一般规则,即具有约束违规的程序具有未定义的行为.标准没有明确说明.它将"约束"定义为

限制,语法或语义,通过它来解释语言元素的阐述

我自己的解释是,如果违反约束,就没有有效的解释,因此行为是不确定的,但也有一些人不同意.我想在未来的标准中看到这种效果的明确声明.

我认为C标准的措辞在这一点上确实含糊不清.

如果没有这样的一般规则,则不清楚行为是否未定义.在陈述此代码违反的约束之后,标准继续定义return语句的语义:

一个return语句终止函数的执行和控制权返回给调用者.

即使存在此约束违规,该描述仍然有意义.可以合理地假设,虽然它没有完全说明,但return;相当于达到收盘价},这相当于return 0;(这是mainN1570 5.1.2.2.3 的特殊情况规则).

另一方面,描述是明确的并不是100%清楚.return;相当于达成收盘价的论点}特别薄弱.因此,即使在没有一般规则的情况下,也可以认为行为是由于遗漏而未定义(没有行为的定义).

return;显然是一个约束违规,并且在我看来,如果实现产生可执行文件,它具有未定义的行为.当然,也允许符合标准的编译器完全拒绝该程序; 在这种情况下,它根本没有任何行为.

底线:这是很多很多 很多容易改变return;return 0;比来回答这个问题.

我鼓励其他语言律师反驳这个答案.我在这里做了足够的内部不一致的论点,它应该不会太难.

  • @haccks:我开始怀疑我们是否在看同一份文件.`return`语句在N1570 6.8.6.4中规定.在该小节中,恰好有两次出现**will**.两者都在第1段中,这是**约束**部分的全部内容.如何超出约束范围? (2认同)
  • @haccks:约束违规允许编译器完全拒绝该程序.在这种情况下,没有行为,定义或其他.但是,如果实现通过非致命警告诊断出约束违规,然后生成可执行文件,则不清楚该行为是否必定未定义.我认为标准在这一点上还不清楚.如果标准未定义行为,则行为未定义. (2认同)
  • 在其他情况下......好吧,"约束"的定义是"限制,无论是句法还是语义,通过它来解释语言元素的阐述".如果违反约束,可以说没有办法解释语言元素.(我个人认为标准*应该*表示如果违反约束,行为是未定义的,但我不确定它是否确实存在.) (2认同)