0

In what way(s), if any, does the C++ standard limit the effect of undefined behavior? For instance, in the code below, from the first if inspecting undefined is control flow constrained to follow either the then path or the else path? Is it allowed to skip both paths? Execute both paths (potentially in parallel)? Take a wild jump into the middle of the second if?

void f(int undefined) {
    bool startNuclearWar = true;

    if (undefined > 0) {
        printf("True path\n");
        startNuclearWar = false;
    } else {
        printf("False path\n");
        startNuclearWar = false;
    }

    if (startNuclearWar) {
        lauchMissles();
    }
}
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
John Yates
  • 1,027
  • 1
  • 7
  • 18

3 Answers3

2

The standard has no constraints on UB. The moment you do anything which invokes UB, the standard guarantees nothing about what happens.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Actually, UB takes effect from the moment that external input sets the program on the path to something that will eventually invoke undefined behavior. – Sebastian Redl Mar 22 '18 at 19:42
  • @SebastianRedl - not true. UB can result from input (e.g. user input results in an overflow of an `int` in some subsequent statement) but that doesn't mean UB takes effect from the moment of input. Input can affect whether a statement is reached that has UB, but - until some statement actually exhibits UB, the behaviour of each preceding statement is well defined. – Peter Mar 23 '18 at 09:14
  • @Peter: N4727 [intro.abstract]p5: "However, if any such execution contains an undefined operation, this document places no requirement on the implementation executing that program with that input **(not even with regard to operations preceding the first undefined operation)**." UB works backwards in time. – Sebastian Redl Mar 23 '18 at 09:32
0

While there are many situations where it would be useful to be able to "compartmentalize" undefined behavior, and while doing so would be inexpensive on many platforms, the people writing Standards have not shown any significant interest in doing so. The C11 Standard offers Annex L about "analyzability" but it fails to describe anything meaningful that an implementation would have to guarantee if defines __STDC_ANALYZABLE__.

The fact that integer overflow is Bounded Undefined Behavior, for example, would be of limited use without clean a way to ensure that code like the following:

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

will use the same value for index in the comparison and in the array lookup.

Many implementations could cheaply offer many useful guarantees beyond those required by the Standard, especially in application fields where it would be acceptable for a program to abnormally terminate when given invalid input, but not acceptable for it to let maliciously-constructed input take control of the machine. Unfortunately, the Standard fails to provide the necessary hooks to efficiently take advantage of that (e.g. providing an intrinsic which would take a value that may be Indeterminate and produce a value which is at worst Unspecified). Applying such an intrinsic to the value in index in the code above before performing the comparison would ensure that even if an overflow occurs in computeSomething, code would be guaranteed to either increment a value within the array, or notice that index was invalid. Since neither operation would results in Critical Undefined Behavior, execution would thus stay on the rails.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

In what way(s), if any, does the C++ standard limit the effect of undefined behavior?

None whatsoever. Undefined behavior is undefined by its nature, so absolutely anything can happen. And once something undefined has happened, the state of the program is unknown from that point on.

That being said, there is no undefined behavior in the code you have showed. Everything in the code has defined behavior.

For instance, in the code below, from the first if inspecting undefined is control flow constrained to follow either the then path or the else path?

Yes.

Is it allowed to skip both paths?

No.

Execute both paths (potentially in parallel)?

No.

Take a wild jump into the middle of the second if?

No.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • If undefined behaviour has occurred in any previously executed code, then the answers to the questions are exactly the opposite of what yoi have given. ;-) – Peter Mar 22 '18 at 19:41
  • Actually, the state of the program is unknown *backwards in time*, to account for reordering optimizations and other modifications. – Sebastian Redl Mar 22 '18 at 19:41
  • @Peter: even if UB did occur, I wouldn't expect language constructs like `if` to stop working the way they are defined to work. UB might affect the *data* they operate on, though. Unless the UB trashes memory that happens to contain the `if`'s executable code. – Remy Lebeau Mar 22 '18 at 19:54