Questions tagged «undefined-behavior»

编译或执行程序的不可预测结果破坏了编译器,解释器或运行时系统都不必执行的语言规则。请勿对数据类型或返回值“ undefined”的问题使用此标记。在这些情况下,应改用[undefined]标签。

5
未定义的行为和顺序点
什么是“序列点”? 未定义行为与序列点之间有什么关系? 我经常使用诸如的有趣且令人费解的表情a[++i] = i;来使自己感觉更好。为什么我应该停止使用它们? 如果您已阅读本文,请确保访问后续问题未定义行为和重载序列点。 (注意:这本来是Stack Overflow的C ++ FAQ的一个条目。如果您想批评以这种形式提供FAQ的想法,那么开始所有这些工作的meta上的发布将是这样做的地方。该问题在C ++聊天室中进行监控,该问题最初是从FAQ想法开始的,所以提出这个想法的人很可能会读懂您的答案。)




5
C ++标准是否允许未初始化的bool使程序崩溃?
我知道C ++ 中的“未定义行为”几乎可以允许编译器执行其想要的任何操作。但是,由于我认为代码足够安全,因此发生了一次崩溃,这让我感到惊讶。 在这种情况下,真正的问题仅在使用特定编译器的特定平台上发生,并且仅在启用优化后才发生。 为了重现此问题并将其简化到最大程度,我尝试了几件事。下面是一个函数的提取物被称为Serialize,这将需要一个布尔参数,并复制字符串true或false到现有的目标缓冲区。 此功能是否在代码审查中,如果bool参数是未初始化的值,实际上没有办法告诉它崩溃吗? // Zero-filled global buffer of 16 characters char destBuffer[16]; void Serialize(bool boolValue) { // Determine which string to print based on boolValue const char* whichString = boolValue ? "true" : "false"; // Compute the length of the string we selected const size_t len = …

22
未初始化的局部变量是最快的随机数生成器吗?
我知道未初始化的局部变量是未定义的行为(UB),并且该值可能具有陷阱表示,这可能会影响进一步的操作,但是有时我只想将随机数用于视觉表示,而不会在其他部分使用它们程序,例如,在视觉效果中设置具有随机颜色的内容,例如: void updateEffect(){ for(int i=0;i<1000;i++){ int r; int g; int b; star[i].setColor(r%255,g%255,b%255); bool isVisible; star[i].setVisible(isVisible); } } 比那快吗 void updateEffect(){ for(int i=0;i<1000;i++){ star[i].setColor(rand()%255,rand()%255,rand()%255); star[i].setVisible(rand()%2==0?true:false); } } 并且比其他随机数生成器还快?

11
为什么f(i = -1,i = -1)未定义行为?
我正在阅读有关评估违规的顺序,它们举了一个令人困惑的例子。 1)如果相对于同一标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。 // snip f(i = -1, i = -1); // undefined behavior 在这种情况下,i是标量对象,这显然意味着 算术类型(3.9.1),枚举类型,指针类型,指向成员类型的指针(3.9.2),std :: nullptr_t和这些类型的cv限定版本(3.9.3)统称为标量类型。 在这种情况下,我看不出该陈述的模棱两可。在我看来,无论是第一个还是第二个参数都首先被求值,结果i都为-1,并且两个参数也都是-1。 有人可以澄清一下吗? 更新 我非常感谢所有讨论。到目前为止,我非常喜欢@harmic的答案,因为尽管乍一看看上去很直截了当,但它暴露了定义此语句的陷阱和复杂性。@ acheong87指出了使用引用时出现的一些问题,但我认为这与该问题的无序副作用方面是正交的。 摘要 既然这个问题引起了很多关注,我将总结要点/答案。首先,请允许我指出一下“为什么”可能具有紧密相关但又微妙的不同含义,即“出于何种原因 ”,“出于何种原因 ”和“出于何种目的 ”。我将按照回答“为什么”的含义中的哪一个分组答案。 是什么原因 这里的主要答案来自Paul Draper,Martin J做出了类似但不太广泛的答案。保罗·德雷珀(Paul Draper)的答案归结为 这是未定义的行为,因为未定义行为是什么。 就解释C ++标准所说的内容而言,答案总体来说是非常好的。它还解决了UB的一些相关情况,例如f(++i, ++i);和f(i=1, i=-1);。在第一种相关情况下,不清楚第一个参数是否应为i+1第二个参数,i+2反之亦然;在第二个中,不清楚i函数调用后应为1还是-1。这两种情况都是UB,因为它们属于以下规则: 如果相对于相同标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。 因此,f(i=-1, i=-1)UB也是如此,因为它属于同一规则,尽管程序员(IMHO)的意图是明显且明确的。 保罗·德雷珀(Paul Draper)在其结论中也明确指出: 可以定义行为吗?是。定义好了吗?没有。 这带给我们一个问题:“由于什么原因/目的f(i=-1, i=-1)留下未定义的行为?” 由于什么原因/目的 尽管C ++标准中存在一些疏漏(可能是粗心大意),但是许多遗漏是有道理的,并且可以满足特定的目的。尽管我知道目的通常是“使编译器-编写器的工作更轻松”或“更快的代码”,但我主要还是想知道是否有充分理由离开 f(i=-1, i=-1) …

14
为什么此for循环在某些平台上而不在其他平台上退出?
我最近开始学习C,并且正在上一门以C为主题的课程。我目前正在玩循环,并且遇到了一些奇怪的行为,我不知道该如何解释。 #include <stdio.h> int main() { int array[10],i; for (i = 0; i <=10 ; i++) { array[i]=0; /*code should never terminate*/ printf("test \n"); } printf("%d \n", sizeof(array)/sizeof(int)); return 0; } 在运行Ubuntu 14.04的笔记本电脑上,此代码未中断。它运行到完成。在我学校的运行CentOS 6.6的计算机上,它也可以正常运行。在Windows 8.1上,循环永远不会终止。 更奇怪的是,当我将for循环条件编辑为:时i <= 11,代码仅在运行Ubuntu的笔记本电脑上终止。它永远不会在CentOS和Windows中终止。 谁能解释内存中发生了什么,以及为什么运行相同代码的不同OS会产生不同的结果? 编辑:我知道for循环超出范围。我是故意的 我只是无法弄清楚在不同的操作系统和计算机上行为如何不同。

5
为什么未定义整数溢出定义行为,但没有定义整数溢出?
C和C ++标准都很好地定义了无符号整数溢出。例如,C99标准(§6.2.5/9)指出 涉及无符号操作数的计算永远不会溢出,因为无法用所得的无符号整数类型表示的结果的模数要比该所得类型可以表示的最大值大一模。 但是,两个标准都指出有符号整数溢出是未定义的行为。同样,根据C99标准(§3.4.3/1) 未定义行为的一个示例是整数溢出时的行为 是否存在这种差异的历史原因(甚至更好!)是技术原因?

11
C ++程序员应该知道哪些常见的未定义行为?[关闭]
很难说出这里的要求。这个问题是模棱两可,含糊,不完整,过于宽泛或夸张的,因此不能以当前的形式合理地回答。如需帮助澄清此问题以便可以重新打开, 请访问帮助中心。 7年前关闭。 已锁定。该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 C ++程序员应该知道哪些常见的未定义行为? 像这样说: a[i] = i++;

15
实际上,为什么不同的编译器会计算int x = ++ i + ++ i;的不同值?
考虑以下代码: int i = 1; int x = ++i + ++i; 我们假设编译器对此代码可能进行编译时有一些猜测。 两者都++i返回2,导致x=4。 一个++i返回2,另一个返回3,导致x=5。 两者都++i返回3,导致x=6。 在我看来,第二次出现的可能性最大。使用++运算符执行两个运算符之一i = 1,将i其递增,然后2返回结果。然后,使用++来执行第二个运算符i = 2,将i递增,并3返回结果。然后2与3加在一起得到5。 但是,我在Visual Studio中运行了这段代码,结果是6。我试图更好地理解编译器,并且想知道什么可能导致的结果6。我唯一的猜测是代码可以通过一些“内置”并发执行。++调用了两个运算符,每个运算符i在另一个返回之前先递增,然后都返回3。这将与我对调用堆栈的理解相矛盾,因此需要加以解释。 C++编译器可能会执行哪些(合理的)操作,从而导致结果4或结果或6? 注意 该示例在Bjarne Stroustrup的《编程:使用C ++的原理和实践》中作为未定义行为的示例出现。 参见肉桂的评论。

5
为什么此循环会产生“警告:迭代3u调用未定义的行为”并输出多于4行?
编译此: #include <iostream> int main() { for (int i = 0; i < 4; ++i) std::cout << i*1000000000 << std::endl; } 并gcc产生以下警告: warning: iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations] std::cout << i*1000000000 << std::endl; ^ 我知道有符号整数溢出。 我无法获得的是为什么i值被该溢出操作破坏了? 我已经阅读了以下答案:为什么在带有GCC的x86上整数溢出会导致无限循环?,但我仍然不清除,为什么出现这种情况-我得到“未定义”是指“任何事情都可能发生”,但有什么的根本原因这个特定的行为? 在线:http://ideone.com/dMrRKR 编译器: gcc (4.8)

8
优化了“ while(1);” 在C ++ 0x中
更新,请参见下文! 我听说过,C ++ 0x允许编译器为以下代码段打印“ Hello” #include <iostream> int main() { while(1) ; std::cout << "Hello" << std::endl; } 显然,它与线程和优化功能有关。在我看来,这会让很多人感到惊讶。 有人对为什么要允许这样做有很好的解释吗?作为参考,最新的C ++ 0x草案在6.5/5 在for语句的情况下,在for-init-statement之外的循环, 不调用库I / O函数,并且 不访问或修改易失性对象,并且 不执行任何同步操作(1.10)或原子操作(第29条) 实现可能会假定它终止。[注意:这旨在允许编译器进行转换,例如删除空循环,即使无法证明终止也是如此。—尾注] 编辑: 这篇有见地的文章谈到了该标准文本 不幸的是,没有使用“未定义行为”一词。但是,只要该标准说“编译器可以假定P”,就意味着具有not-P属性的程序具有未定义的语义。 这是正确的,并且允许编译器为上述程序打印“ Bye”吗? 这里有一个更具洞察力的线程,它与对C的类似更改有关,由Guy在上面的链接文章中开始。在其他有用的事实中,他们提出了一种似乎也适用于C ++ 0x的解决方案(更新:在n3225上将不再起作用-参见下文!) endless: goto endless; 看来,不允许编译器对其进行优化,因为这不是循环,而是跳转。另一个人总结了C ++ 0x和C201X的拟议更改 通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I / O,访问volatile对象,或进行同步或原子操作), 或者,它最终会终止。如果我通过写一个没有副作用的无限循环违反了这一假设,那我就是对编译器撒谎,而我的程序的行为是不确定的。(如果幸运的话,编译器可能会警告我。)该语言不提供(不再提供?)一种表达无可见行为的无限循环的方法。 在2011年3月31日更新了n3225:委员会将文本移至1.10 / 24并说 …

5
为什么增强的GCC 6优化器会破坏实用的C ++代码?
GCC 6具有新的优化程序功能:假定该this值始终不为null并基于此进行优化。 现在,值范围传播假定C ++成员函数的this指针为非null。这消除了常见的空指针检查,但也破坏了一些不合格的代码库(例如Qt-5,Chromium,KDevelop)。作为临时解决方法,可以使用-fno-delete-null-pointer-checks。使用-fsanitize = undefined可以识别错误的代码。 变更文档显然将此称为危险,因为它破坏了数量惊人的频繁使用的代码。 为什么这个新假设会破坏实用的C ++代码?粗心或不了解信息的程序员是否有特定的模式依赖于这种特定的未定义行为?我无法想象有人写作,if (this == NULL)因为那太不自然了。

6
为什么带有GCC的x86上的整数溢出会导致无限循环?
以下代码在GCC上进入了无限循环: #include <iostream> using namespace std; int main(){ int i = 0x10000000; int c = 0; do{ c++; i += i; cout << i << endl; }while (i > 0); cout << c << endl; return 0; } 所以这是要解决的问题:有符号整数溢出在技术上是未定义的行为。但是x86上的GCC使用x86整数指令实现了整数算术-溢出会自动换行。 因此,尽管它是未定义的行为,但我希望它能溢出。但这显然不是事实。那我想念什么? 我使用以下代码编译了此代码: ~/Desktop$ g++ main.cpp -O2 GCC输出: ~/Desktop$ ./a.out 536870912 1073741824 …
129 c++  c  gcc  x86  undefined-behavior 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.