未定义的行为

如果程序包含未定义的行为,则 C++标准不会对其行为施加任何约束。

  • 它可能看起来像开发人员的意图,但它也可能崩溃或产生奇怪的结果。
  • 行为可能因同一程序的运行而异。
  • 程序的任何部分都可能出现故障,包括在包含未定义行为的行之前的行。
  • 不需要实现来记录未定义行为的结果。

实现可以记录根据标准产生未定义行为的操作的结果,但是依赖于这种记录的行为的程序是不可移植的。

为什么存在未定义的行为

直觉上,未定义的行为被认为是一件坏事,因为这样的错误无法通过异常处理程序来处理。

但是保留一些未定义的行为实际上是 C++承诺的一个组成部分,你不为你不使用的东西买单。未定义的行为允许编译器假设开发人员知道他在做什么,而不是引入代码来检查上面示例中突出显示的错误。

查找并避免未定义的行为

某些工具可用于在开发期间发现未定义的行为:

  • 大多数编译器都有警告标志来警告编译时某些未定义行为的情况。
  • 较新版本的 gcc 和 clang 包含一个所谓的 Undefined Behavior Sanitizer 标志(-fsanitize=undefined),它将在运行时以性能成本检查未定义的行为。
  • 类似 lint 的工具可以执行更彻底的未定义行为分析。

未定义,未指定和实现定义的行为

从 C++ 14 标准(ISO / IEC 14882:2014)第 1.9 节(程序执行):

  1. 本国际标准中的语义描述定义了参数化的非确定性抽象机器。 [切]

  2. 抽象机的某些方面和操作在本国际标准中描述为实现定义的 (例如,sizeof(int))。这些构成了抽象机器的参数。每个实施应包括描述其在这些方面的特征和行为的文件。 [切]

  3. 抽象机器的某些其他方面和操作在本国际标准中被描述为未指定的 (例如,如果分配函数未能分配存储器,则评估新初始化器中的表达式 )。在可能的情况下,本国际标准定义了一组允许的行为。这些定义了抽象机器的非确定性方面。因此,抽象机器的实例可以对给定程序和给定输入具有多于一个可能的执行。

  4. 本国际标准中将某些其他操作描述为未定义 (或者,例如,尝试修改 const 对象的效果)。 [ 注意 :本国际标准对包含未定义行为的程序的行为没有要求。 - 结束说明 ]