为了账号安全,请及时绑定邮箱和手机立即绑定

“未定义的行为”真的允许*任何事情发生吗?

“未定义的行为”真的允许*任何事情发生吗?

C++ C
婷婷同学_ 2019-07-09 15:19:00
“未定义的行为”真的允许*任何事情发生吗?这个问题并不是用来讨论未定义行为的优点的论坛,但它就是这样的。无论如何,这个线程是关于一个假设的C-编译器,没有未定义的行为。对于那些认为这是一个重要话题的人来说,可能会有更多的兴趣。典型的“未定义的行为”的例子,当然是“鼻涕鬼”-不管C和C+标准允许什么,都是一种生理上的不可能。因为C和C+社区倾向于强调未定义行为的不可预见性,以及编译器允许程序按字面顺序执行的想法。什么都行当遇到未定义的行为时,我假设标准对未定义行为的行为没有任何限制。但C+标准中的相关引用似乎是:[C++14: defns.undefined]: [..]允许的未定义行为包括:完全忽略这种情况而导致不可预测的结果;在翻译或程序执行过程中以具有环境特征的记录方式(无论是否发布诊断消息);终止翻译或执行(通过发布诊断消息)。[..]这实际上指定了一组可能的选项:无视形势-是的,标准接着说这会有“不可预测的结果”,但这和编译器不一样插入代码(我认为这是鼻腔恶魔的先决条件)。以有文件记录的方式行事,具有环境特征-实际上,这听起来比较温和.(我当然没有听说过任何有记录的鼻涕病例。)终止翻译或执行-用诊断法,也一样.如果所有的UB都能表现得这么好。我假设在大多数情况下,编译器选择忽略未定义的行为;例如,在读取未初始化的内存时,插入任何代码以确保行为一致可能是一种反优化。我认为陌生人的未定义行为类型(如“时间旅行)将属于第二类-但这需要记录这些行为和“环境特征”(因此,我猜鼻恶魔只是由地狱的计算机产生的?)。我是不是误解了定义?这些仅仅是实例什么可以构成未定义的行为,而不是一个全面的选项列表?所谓“任何事情都可能发生”的说法是否仅仅意味着无视形势的意外副作用?编辑:有两点需要澄清:我认为从最初的问题中可以看出这一点,我认为对大多数人来说都是如此,但我还是会说出来的:我确实意识到“鼻涕鬼”是开玩笑的。请不要写(其他)答案,说明ub允许特定于平台的编译器优化,除非您也解释它是如何允许优化的执行-定义行为不会允许。
查看完整描述

3 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

是的,它允许任何事情发生。这张便条只是举了几个例子。定义相当明确:

未定义的行为:本国际标准对其不施加任何要求的行为。


经常混淆的地方:

你应该明白“没有要求”意味着实现是必须让行为不被定义,或者做一些奇怪的或不确定的事情!

C+标准完全允许该实现记录一些正常的行为并相应地进行操作。1因此,如果您的编译器声称要对签名溢出进行包装,那么逻辑(是否正确?)就意味着你可以依靠这种行为关于那个编译器..只是不要指望另一个编译器会以同样的方式运行,如果它不声称的话。

1见鬼,它甚至可以记录一件事,做另一件事。这将是愚蠢的,它可能会让你把它扔进垃圾桶-你为什么要相信一个编译器,它的文档对你来说是假的?-但这并不违反C+标准。


查看完整回答
反对 回复 2019-07-09
?
白衣非少年

TA贡献1155条经验 获得超0个赞

未定义行为的历史目的之一是允许某些行为有不同的可能性。可能有用对不同平台的影响。例如,在C的早期,

int i=INT_MAX;i++;printf("%d",i);

一些编译器可以保证代码会打印一些特定的值(对于两个互补机器,通常是int_min),而另一些编译器则保证程序将在不到达printf的情况下终止。根据应用程序的需求,这两种行为都可能是有用的。保留未定义的行为意味着,如果程序终止异常是溢出导致的可接受的后果,但产生看似有效但错误的输出,则可能会放弃溢出检查,如果运行在一个平台上,该平台将可靠地捕获溢出,而在溢出情况下出现异常终止的应用程序将无法接受,但如果在没有捕获溢出的平台上运行,则会产生算术错误的输出,则可能会放弃溢出检查。

然而,最近,一些编译器作者似乎参与了一场竞赛,看谁能最有效地消除标准不允许存在的任何代码。比如说.。

#include <stdio.h>int main(void){
  int ch = getchar();
  if (ch < 74)
    printf("Hey there!");
  else
    printf("%d",ch*ch*ch*ch*ch);}

超现代编译器可能会得出结论,如果ch的计算值为74或更大。ch*ch*ch*ch*ch会产生未定义的行为,因此程序应该打印“嘿!”无条件地不管输入了什么字符。


查看完整回答
反对 回复 2019-07-09
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

挑剔:你没有引用标准。

这些是用来生成C+标准草案的源。这些来源不应被视为ISO出版物,除非C+工作组正式通过这些来源产生的文件(ISO/IEC JTC 1/SC 22/WG21)。

解释*注释不是规范性根据ISO/IEC指令第二部分。

纳入文件案文的说明和例子只能用于提供旨在协助理解或使用该文件的补充信息。它们不应包含要求(“应”;见3.3.1和表H.1)或任何被认为对文件的使用必不可少的信息例如指示(祈使句;见表H.1),建议(“应”;见3.3.2和表H.2)或许可(“可”;见表H.3)。笔记可以写成事实陈述。

强调我的。仅这一点就排除了“全面的备选方案清单”。然而,举一些例子确实可以算作“旨在帮助理解该文件的补充资料”。

一定要记住,“鼻恶魔”模因并不是字面意义上的,就像用气球解释宇宙膨胀是如何工作的一样,在物理实相中没有真理。这是为了说明讨论什么“未定义的行为”是鲁莽的在允许做任何事情的时候做。是的,这意味着外层空间没有实际的橡皮筋。


查看完整回答
反对 回复 2019-07-09
  • 3 回答
  • 0 关注
  • 560 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信