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.