未定义、未指定和实现定义的行为 [英] Undefined, unspecified and implementation-defined behavior

查看:44
本文介绍了未定义、未指定和实现定义的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是 C 和 C++ 中的未定义行为 (UB)?未指定的行为实现定义的行为呢?它们有什么区别?

What is undefined behavior (UB) in C and C++? What about unspecified behavior and implementation-defined behavior? What is the difference between them?

推荐答案

未定义行为 是 C 和 C++ 语言中令程序员感到惊讶的方面之一来自其他语言(其他语言试图更好地隐藏它).基本上,即使许多 C++ 编译器不会报告程序中的任何错误,也可以编写不以可预测方式运行的 C++ 程序!

Undefined behavior is one of those aspects of the C and C++ language that can be surprising to programmers coming from other languages (other languages try to hide it better). Basically, it is possible to write C++ programs that do not behave in a predictable way, even though many C++ compilers will not report any errors in the program!

我们来看一个经典的例子:

Let's look at a classic example:

#include <iostream>

int main()
{
    char* p = "hello!
";   // yes I know, deprecated conversion
    p[0] = 'y';
    p[5] = 'w';
    std::cout << p;
}

变量 p 指向字符串文字 "hello! ",下面的两个赋值尝试修改该字符串文字.这个程序有什么作用?根据 C++ 标准的第 2.14.5 节第 11 段,它调用了未定义行为:

The variable p points to the string literal "hello! ", and the two assignments below try to modify that string literal. What does this program do? According to section 2.14.5 paragraph 11 of the C++ standard, it invokes undefined behavior:

尝试修改字符串文字的效果未定义.

The effect of attempting to modify a string literal is undefined.

我可以听到人们在尖叫但是等等,我可以毫无问题地编译它并获得输出yellow";或您是什么意思未定义,字符串文字存储在只读内存中,因此第一次分配尝试会导致核心转储".这正是未定义行为的问题.基本上,一旦您调用未定义的行为(甚至是鼻恶魔),该标准就会允许任何事情发生.如果有一个正确"根据您对语言的心理模型的行为,该模型完全是错误的;C++ 标准拥有唯一的投票权,句号.

I can hear people screaming "But wait, I can compile this no problem and get the output yellow" or "What do you mean undefined, string literals are stored in read-only memory, so the first assignment attempt results in a core dump". This is exactly the problem with undefined behavior. Basically, the standard allows anything to happen once you invoke undefined behavior (even nasal demons). If there is a "correct" behavior according to your mental model of the language, that model is simply wrong; The C++ standard has the only vote, period.

未定义行为的其他示例包括访问超出其边界的数组、取消引用空指针在对象生命周期结束后访问对象 或编写据称是聪明的表达式,例如<代码>i++ + ++i.

Other examples of undefined behavior include accessing an array beyond its bounds, dereferencing the null pointer, accessing objects after their lifetime ended or writing allegedly clever expressions like i++ + ++i.

C++ 标准的第 1.9 节还提到了未定义行为的两个不太危险的兄弟,未指定行为实现定义的行为:

Section 1.9 of the C++ standard also mentions undefined behavior's two less dangerous brothers, unspecified behavior and implementation-defined behavior:

本国际标准中的语义描述定义了一个参数化的非确定性抽象机器.

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine.

抽象机的某些方面和操作在本国际标准中被描述为实现定义(例如,sizeof(int)).这些构成了抽象机的参数.每个实现都应包含描述其在这些方面的特征和行为的文档.

Certain aspects and operations of the abstract machine are described in this International Standard as implementation-defined (for example, sizeof(int)). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects.

抽象机的某些其他方面和操作在本国际标准中被描述为未指定(例如,函数参数的求值顺序).在可能的情况下,本国际标准定义了一组允许的行为.这些定义了抽象机器的不确定性方面.

Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function). Where possible, this International Standard defines a set of allowable behaviors. These define the nondeterministic aspects of the abstract machine.

本国际标准中将某些其他操作描述为未定义(例如,取消引用空指针的效果).[ 注意:本国际标准对包含未定义行为的程序的行为没有要求.尾注 ]

Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer). [ Note: this International Standard imposes no requirements on the behavior of programs that contain undefined behavior.end note ]

具体而言,第 1.3.24 节规定:

Specifically, section 1.3.24 states:

允许的未定义行为范围从完全无视情况并产生不可预测的结果,在翻译或程序执行期间以环境特征的记录方式行为(有或没有发布诊断消息),终止翻译或执行(发出诊断消息).

Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

你能做些什么来避免遇到未定义的行为?基本上,您必须阅读了解自己在说什么的作者的优秀的 C++ 书籍.避免网络教程.避免废话.

What can you do to avoid running into undefined behavior? Basically, you have to read good C++ books by authors who know what they're talking about. Avoid internet tutorials. Avoid bullschildt.

这篇关于未定义、未指定和实现定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆