8

Consider this program:

#include <stdio.h>

int main(void)
{
    int x;
    while ( 1 == scanf("%d", &x) )
        printf("%c\n", "hello"[x]);
}

The compiler must compile this successfully because the program has no UB so long as the user does not enter any numbers outside the range 0-4.

However, according to this thread UB can travel back in time. Now consider this program:

int main(void)
{ 
    printf("hello\n");
    "hello"[6];
}

Any invocation of this program results in undefined behaviour, and since that can time-travel, the entire behaviour of this program on any invocation is undefined. Can the compiler therefore reject the program and not generate an executable? (We might say that the UB travels back in time to the compilation stage!)

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • 5
    @Zaffy: `"hello"[5]` is `'\0'`, `"hello"[6]` is out of bound. – Jarod42 Dec 19 '14 at 09:58
  • @Jarod42 oh, yeah, sorry :) – Zaffy Dec 19 '14 at 09:59
  • 2
    Reliable and sound detection of undefined behavior is an untractable or undecidable problem.... – Basile Starynkevitch Dec 19 '14 at 10:00
  • 1
    Yes, the perfect example of this is `constexpr`, we can see `clang` and `gcc` reject [most undefined behavior at compile time](http://stackoverflow.com/a/21319414/1708801) in these cases. – Shafik Yaghmour Dec 19 '14 at 10:38
  • As a note, there are cases of UB where aborting compilation is common: For example, Gcc aborts on `void foo(void) { extern int n; } static int n;`, although this is UB and not a constraint violation. Your example is a little different, though, IMO. – mafso Dec 19 '14 at 10:39
  • The C language has on built-in boundary protection, so this will compile with no errors. But there will be a warning about a do-nothing line. However, the referenced char will be the first character of the next literal in the .const section of the executable – user3629249 Dec 19 '14 at 11:12
  • The compiler can stop translation in the second program (as it invokes UB) but it cannot stop translation in the first program (as not all execution paths invoke UB). – ouah Dec 19 '14 at 15:44

2 Answers2

14

Can the compiler therefore reject the program and not generate an executable?

Yes. The definition of undefined behaviour is:

behavior for which this International Standard imposes no requirements [ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. 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). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
4

To add to Jonathan's answer.

The second program invokes undefined behavior and a compiler has the right to stop the translation as undefined behavior is not bounded (c11, 3.4.3p1).

The first program may invoke undefined behavior but the compiler cannot stop the translation as not all execution paths produce undefined behavior.

In Defect Report #109, C Committee says:

Furthermore, if every possible execution of a given program would result in undefined behavior, the given program is not strictly conforming. A conforming implementation must not fail to translate a strictly conforming program simply because some possible execution of that program would result in undefined behavior.

ouah
  • 142,963
  • 15
  • 272
  • 331