了解未定义行为的范围

Understanding the scope of undefined behavior

本文关键字:范围 未定义 了解      更新时间:2023-10-16

C++标准以何种方式(如果有的话)限制了未定义行为的影响? 例如,在下面的代码中,从第一个if开始检查undefined控制流是否受限于遵循当时路径或 else 路径? 是否允许跳过两条路径?执行两条路径(可能并行执行)?狂野地跳到第二if中间?

void f(int undefined) {
bool startNuclearWar = true;
if (undefined > 0) {
printf("True pathn");
startNuclearWar = false;
} else {
printf("False pathn");
startNuclearWar = false;
}
if (startNuclearWar) {
lauchMissles();
}
}

该标准对 UB 没有限制。当你做任何调用UB的事情时,标准并不能保证会发生什么。

虽然在许多情况下,能够"划分"未定义的行为是有用的,并且虽然这样做在许多平台上会很便宜,但编写标准的人并没有表现出任何显着的兴趣。 C11标准提供了关于"可分析性"的附录L,但它没有描述任何有意义的东西,如果定义__STDC_ANALYZABLE__,实现必须保证。

例如,整数溢出是有界未定义行为的事实,如果没有一种干净的方法来确保代码如下,那么它的用处将是有限的:

int index = computeSomething();
if (index < 0 || index >= ARRAYSIZE) FatalError();
myArray[index]++;

将在比较和数组查找中对index使用相同的值。

许多实现可以廉价地提供超出标准要求的许多有用保证,特别是在应用领域,当给定无效输入时,程序异常终止是可以接受的,但不允许恶意构造的输入控制机器。 不幸的是,该标准未能提供必要的钩子来有效地利用这一点(例如,提供一个内在的,该内在函数将采用一个可能不确定的值,并产生一个最坏的情况是未指定的值)。 在执行比较之前,将这样的内在应用于上述代码中index的值将确保即使在computeSomething中发生溢出,代码也会保证在数组中增加一个值,或者注意到index无效。 由于这两个操作都不会导致严重未定义行为,因此执行将保持在轨道上。

C++标准以何种方式(如果有的话)限制了未定义行为的影响?

都不是。 未定义的行为本质上是未定义的,因此绝对可能发生任何事情。 一旦发生了未定义的事情,程序的状态从那时起就未知了。

话虽如此,您显示的代码中没有未定义的行为。 代码中的所有内容都有定义的行为。

例如,在下面的代码中,从第一个if开始检查undefined控制流是否受限于遵循当时路径或 else 路径?

是的。

是否允许跳过两条路径?

不。

执行两条路径(可能并行执行)?

不。

疯狂地跳到秒中间如果?

不。