The most horrifying aspect of UB is that it can affect your program without the instructions triggering it ever being executed. And many greenhorns don't know that or even believe it to be false. So the effects of Dunning-Kruger may be more severe in C(++) than in other languages.
It’s not just “there’s a line in some file that’s undefined” partly because undefined behavior is often caused by the state of the world. Dereferencing a pointer is defined unless the pointer is invalid, and any particular pointer may be valid sometimes and invalid others.
But since a compiler can do anything when a program is ill-defined, if a line of code could be well-defined in some cases and ill-defined in others, a compiler is allowed to only handle the well-defined cases, knowing that it will do the “wrong” thing when something about the code is undefined (because in that case, there is no “right” or “wrong” behavior.
This does lead to weird things:
auto val = *ptr;
if (!ptr) {
. . .
}
The compiler can delete the “if” statement because the potential undefined behavior happens before the check. Either the pointer is valid when dereferenced (and the “if” statement gets skipped), or the pointer is invalid, and skipping the “if” statement is acceptable for “the compiler can do anything, even things that can’t be expressed in the language.” But it only does the weird things in cases where an invalid pointer would have been dereferenced.