问题标签 [unspecified-behavior]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 未指定、未定义和实现定义的行为 WIKI for C
尽管在 SO 上有很多关于这个主题的链接,但我认为缺少一些东西:用通俗易懂的语言清楚地解释未指定行为(UsB)、未定义行为(UB) 和实现定义行为(IDB ) 之间的区别) 对任何用例和示例进行详细而简单的解释。
注意:我做了UsB的首字母缩写词,但不要期望在其他地方看到它。
我知道这可能看起来与其他帖子重复(更接近的是这个),但在有人将其标记为重复之前,请考虑一下我已经找到的所有材料有什么问题(我将来自这篇文章的社区 WIKI):
太多分散的例子。当然,例子还不错,但有时找不到一个能很好地解决他手头的问题的例子,所以它们可能会令人困惑(尤其是对于新手来说)。
示例通常只是很少解释的代码。在这些微妙的问题上,尤其是对于(相对)新手来说,更自上而下的方法可能会更好:首先是带有抽象(但不是合法的)描述的清晰、简单的解释,然后是 一些简单的例子,解释为什么它们会触发某些行为.
有些帖子经常混合使用 C 和 C++ 示例。C 和 C++ 有时在他们认为的 UsB、UB 和 IDB 上不一致,因此对于不精通这两种语言的人来说,一个示例可能会产生误导。
当给出 UsB、UB 和 IDB 的定义时,通常是对标准的简单引用,对于新手来说有时可能不清楚或太难消化。
有时对标准的引用是部分的。许多帖子仅引用对手头问题有用的部分的标准,这很好,但缺乏通用性。此外,标准的引用通常没有任何解释(对初学者不利)。
由于我自己不是这个主题的超级专家,所以我将创建一个社区 WIKI,以便任何有兴趣的人都可以贡献和改进答案。
为了不破坏我创建结构化的初学者友好 WIKI 的目的,我希望海报在编辑 WIKI 时遵循一些简单的准则:
对您的用例进行分类。如果适用,请尝试将您的示例/代码放在现有类别下,否则创建一个新类别。
首先是简单的文字描述。首先用简单的词语描述(当然不要过度简化——质量第一!)你试图提出的例子或观点。然后放代码示例或引用。
通过引用引用标准。不要发布各种标准的片段,但要给出明确的参考(例如 C99 WG14/N... 第 1.4.7 节,第 ...),并尽可能发布相关资源的链接。
更喜欢免费的在线资源。如果你想引用书籍或非免费资源,那没关系(并且可能会提高 WIKI 的质量),但也可以尝试添加一些免费资源的链接。这对于 ISO 标准尤其重要。欢迎您添加指向官方标准的链接,但也尝试添加指向免费草稿的等效链接。并且请不要将草稿链接替换为对官方标准的引用,添加到它们中。甚至一些大学的一些计算机科学系也没有 ISO 标准的副本,更不用说大多数程序员了!
除非真的有必要,否则不要发布代码。仅当仅使用简单英语的解释会尴尬或不清楚时才发布代码。尝试将代码示例限制为单行。而是发布指向其他 SO Q&A 的链接。
不要发布 C++ 示例。我希望这成为 C 的一种常见问题解答(如果有人想为 C++ 启动一个双线程,那就太好了)。欢迎与 C++ 的相关差异,但仅作为旁注。那是在您彻底解释 C 案例之后,您可以添加一些关于 C++ 的语句,如果这对 C 程序员切换到 C++ 时有所帮助,但我不想看到超过 20% 的 C++ 内容的示例。通常像“(C++ 在这种情况下表现不同)”这样的简单注释加上相关链接就足够了。
由于我对 SO 还很陌生,因此我希望通过这种方式开始问答不会违反任何规则。对不起,如果是这种情况。欢迎模组让我知道。
c++ - func() + func() 是未定义的行为吗?
我只知道i = i++;
是未定义的行为,但是如果在一个表达式中调用了两个或多个函数,并且所有函数都是相同的。它是未定义的吗?例如:
c++ - inexplicable cuda behavior related to memory
so basically i took my c++ code (which is working correctly) and rewrite it to cuda (i have no experience with cuda). The one part of the code (solve() method) is not working correctly and i really dont know why.
So my question is what exactly means "unspecified launch failure" error during cudaMemcpy and why is it happening in my code.
My second question is why variables backup_ans and ans differs when they compute the same thing?
All code except solve() method works as intend. solve() method just computes bullshit (because backup_ans and ans differ) and it is also giving me the "unspecified launch failure" error on last two cudaMemcpy. When i run solve<<<1,1>>>(...) i got
ans: 134816642 backup_ans 432501552
but when i run solve<<<400,32>>>(...) it gives me
ans: 134816642 backup_ans 0 (correct answer should be 0)
In all situations it should compute backup_ans=ans=0
Any advice what i am doing wrong would be helpful.
Code for generating primes.bin
PS: i am compiling it by nvcc -arch compute_11
c++ - 什么时候可以做/使用具有未指定行为的东西?
在 C++ 中,有些东西出现在定义明确和未定义之间。具体来说,它们被称为实现定义和未指定。现在,我对未指定的东西很感兴趣。
什么时候可以使用这些功能,什么时候应该避免使用?有没有很好的例子说明未指定的行为是正确代码的一部分?编写软件时,什么时候是最好的选择?
Matt McNabb 提供的定义:
未定义 - 任何事情都可能发生
实现定义 - 有限数量的结果是可能的,编译器的文档必须说明会发生什么
未指定- 有限数量的结果是可能的 - 通常标准描述一组可能的结果
定义明确 - 以上都不是
格式良好的程序 - 编译时没有错误的程序(可能表现出未定义的行为)
后续问题:
宽松的原子算作未指定的还是明确定义的?
标记为从不同角度讨论相同想法的问题的副本。标记为相同的问题讨论了未指定行为的定义,而这里的问题是关于如何以及何时使用它。
c++ - 移动语义和函数顺序评估
假设我有以下内容:
如果我正确理解有关“函数参数的未指定顺序”的 C++ 规则,则此代码是不安全的。如果B
' 的构造函数的第二个参数首先使用 move 构造函数构造,那么a
现在包含 anullptr
并且表达式a->x
将触发未定义的行为(可能是 segfault)。如果首先构造第一个参数,那么一切都会按预期工作。
如果这是一个普通的函数调用,我们可以创建一个临时的:
但是在类初始化列表中我们没有创建临时变量的自由。
假设我不能改变B
,有没有可能的方法来完成上述?即unique_ptr
在同一个函数调用表达式中取消引用和移动 a 而不创建临时?
如果您可以更改B
的构造函数但不能添加新的方法,例如setX(int)
怎么办?那会有帮助吗?
谢谢
c++ - 什么时候故意利用未指定的行为可以在不牺牲正确性的情况下提供好处?
我将从所使用术语的背景开始。
正确的
“在理论计算机科学中,当算法相对于规范正确时,算法的正确性就被断言了。” - 堆栈溢出的正确性标记。
不明确的
未定义的行为是允许任何事情发生的地方。实际上,可能发生的事情的可能性是无限的。示例是在 c++ 中取消引用 nullptr,并除以零。
定义明确
这是只有一个结果可能的地方。
实现定义
这是实现改变可能性数量的地方。如果某些实现定义的结果导致定义等同于未定义或明确定义,那么这不是我所指的。
未指定
这是存在大于一种但小于无限种可能性的地方。
利用未指定的行为
我指的是为了某些好处(但当然不限于)性能或程序的正确性,将您的程序开放给未指定的行为的想法。例如,将单线程程序转换为多线程程序可能会“利用”未指定的行为来谋取利益。
这个想法
这就是事情变得有趣的地方。或者,至少潜力是存在的。这是编程的灰色地带。有一些关于什么可以或不可以发生的想法,但是发生的事情既不是明确定义的,也不是未定义的。
一个简单且使用良好的示例将涉及多线程。在使用多个线程时,还有很多未知和不可知的地方。尽管如此,还是使用了多个线程,因为它带来了可能无法获得的主要性能提升。
在不牺牲正确性的情况下,有意识地实施未指定的行为还能带来哪些好处? 需要有一些好处。
对于那些可能想要结束这个想法的人,这将邀请基于意见的答案 - 我反驳说,基于专业知识要求答案的问题是一个例外,并且是允许的。这是我认为这个问题有效且可以接受的基础。这是一个可以回答的问题。
在具体参考我之前类似的问题时,我重新提问是因为我没有正确地表达这个问题。我已经对其进行了重新措辞,现在特别要求在不牺牲程序正确性的情况下显示好处的答案。
c++ - C++ cout side-effect sequencing
Suppose following piece of code:
execution of lines marked as 1
and 2
, being compiled with ideone does the same, it prints following:
From my point of view, what we observe here is unspecified behaviour, as order in which function arguments are resolved is unspecified.
This was a question at an interview, printing above given sequence (without any alternatives) was supposed to be correct answer, but is it really correct?
c - C 中的评估顺序,使用在同一分配中更改变量的函数分配变量
因此,首先,这与我需要指导的家庭作业有关。我不需要代码或任何东西,但这让我发疯,我需要澄清一下。我什至没有问书中的问题。
我有以下代码:
当我运行它时,我得到“a 的值为 20”和“右边的函数调用,40”和“左边的函数调用,40”。
我感到困惑的是,我之前有一个非常相似的问题
sum1 的答案是 46,sum2 的答案是 48,在我看来,这在 codepad.org 的编译器中从左到右评估是有意义的。但是在 Pelles C 编译器中,它是 48。您可以看到第一个问题的代码布局几乎完全相同。
我确实找到了这个链接:在 C 中调用函数之前的参数评估顺序,这似乎可以解释这种不一致,但我想确保我的思路没有偏离。那么可以肯定地说它取决于编译器以及编译器认为最有效的方式吗?
c++ - “C++ 编程语言”第 4 版第 36.3.6 节中的这段代码是否具有明确定义的行为?
在 Bjarne Stroustrup 的The C++ Programming Language 4th edition 部分36.3.6
STL-like Operations中,使用以下代码作为链接示例:
断言在gcc
( see it live ) 和Visual Studio
( see it live ) 中失败,但在使用Clang ( see it live )时它不会失败。
为什么我得到不同的结果?这些编译器中是否有任何一个错误地评估了链接表达式,或者此代码是否表现出某种形式的未指定或未定义的行为?
c++ - 是否未指定标准库头文件是否包含任意头文件?
在 C++ 标准库中的哪些标头保证包含另一个标头中有一个声明?:
C++ 标准库头文件可能以未指定的方式相互包含,因此程序员通常不应该依赖一个头文件包括另一个头文件。[...]
在实践中,情况往往如此。例如,<iostream>
可能包含<string>
,在其他情况下您需要<string>
显式包含。但是,我似乎无法在 N4140 中找到这种情况。我看过:
- §2.9 [lex.header]
- §17.6.1.2 [标题]
- §17.6.2.2 [using.headers]
- §17.6.4.4 [alt.headers]
- §17.6.5.2 [res.on.headers]
我能找到的最接近的是 [using.headers]:
2 翻译单元可以以任何顺序包含库头(第 2 条)。每个都可以被包含多次,与只包含一次没有任何不同的效果,除了每次包含一个
<cassert>
或的效果<assert.h>
取决于NDEBUG的词汇当前定义。178
但这似乎适用于 C++ 程序,而不是标准库:
[using.overview]/1 本节描述 C++ 程序如何访问 C++ 标准库的功能。[...]
以及 [res.on.headers]:
1 C++ 标头可能包含其他 C++ 标头。C++ 头文件应提供出现在其概要中的声明和定义。在其概要中显示为包括其他 C++ 头的 C++ 头应提供出现在这些其他头的概要中的声明和定义。
我认为关键是第一句话,但它并没有明确说它是未指定的行为。它是否在任何地方说明这是未指定的行为,还是只是暗示?