13. But if the line with UB isn't executed, then the program will work normally as if the UB wasn't there. 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. 15. If the line with UB is unreachable code, then the program won't crash because of the UB. 16. If the line with UB is unreachable code, then the program will at least stop running somehow and at some point. This…
For example, if a program looks like this:
void foo(int* const p) {
if (p!=NULL) {
bar(p);
}
*p = 1; //this line would be UB if p could be NULL
//so we are free to assume p is not NULL in this scope
}
It will very likely be optimized to this: void foo(int* const p) {
bar(p);
*p = 1;
}
And even if bar() itself had a line checking if p was not NULL, that will get ellided as well if bar() gets inlined.This is a good example of how UB on a later line can have an impact on earlier lines, or even in other places in the code.
Note that it's not executions which trigger UB, it is source code programs that do.
Edit: fixed const pointer syntax.