c++ - 未定义、未指定和实现定义的行为

标签 c++ c undefined-behavior unspecified-behavior implementation-defined-behavior

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

最佳答案

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

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

#include <iostream>

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

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

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

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

未定义行为的其他示例包括访问超出其范围的数组,dereferencing the null pointer , accessing objects after their lifetime ended或写allegedly clever expressions就像i+++++i

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

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

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 节规定:

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).

如何避免遇到未定义的行为?基本上,你必须阅读good C++ books作者知道自己在说什么。避免网络教程。避免胡言乱语。

关于c++ - 未定义、未指定和实现定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59912037/

相关文章:

c++ - 使用 wxWidgets 绘制形状

c - 如何检查结构体中的变量是否未在 C 中使用?

c++ - 如果我递减 `std::size_t(0)` 是否保证等于 `std::size_t(-1)`?

c - C90 中的无符号整数加法和未定义行为

c++ - 类定义应该放在全局还是局部范围内?

c++ - 计算二维平面上单应性的精度

c++ - 如何使用 libc++ istream_iterator 读取文件中的 0xFF?

c - C中的右手迷宫遍历

c++ - 具有最小 RAM 的 C 程序

c - 将要存储在 int 中的左移 short 是 UNDEFINED 吗?