Edit: The 'undefined' clause here is due to invoking a function at address 0, rather than any lack of variable initialization (since global variables are automatically initialized to 0, as the poster below points out).
Edit: The 'undefined' clause here is due to invoking a function at address 0, rather than any lack of variable initialization (since global variables are automatically initialized to 0, as the poster below points out).
What’s undefined here is calling a function pointer that contains zero. Thus the compiler assumes that it must have been set before being called, and since there’s only one value it could possibly be set to, it must be that value.
Your proposal is basically tantamount to saying that the compiler can never ever delete any read or write to memory that is unused if it can't prove that the memory pointer is non-null (for example, the pointer is an argument to the function--clearly a very common case).
Trying to formally specify what can and can't be done with common undefined cases (like dereferencing memory that results in a trap or reading uninitialized values) turns out to run into issues where the specification unintentionally precludes common optimizations, and it's not always clear how to word semantics in such a way to not do that.
That's right. I would much prefer to take a small performance hit if I might be dereferencing a null pointer than to literally have anything at all happen in that case. If I really need that last little bit of performance I really do want my compiler to insist that my code be correct before it will give it to me rather than take a wild guess at what I really meant to do and get it wrong.
If the compiler is going to be given license to make those kinds of dangerous non-intuitive changes to the program semantics I want that to be evident in the source code. For example, I would like to have to say something like YOU_MAY_ASSUME(NOTNULL(X)) before the compiler can assume that X is a pointer that can be dereferenced without signaling an error if it's null. That way the optimizations are still available, but it is easy to tell by looking at the source code if the author prioritized speed over safety and if there are potential gotchas hiding in the code as a result. The way it is now, the potential gotchas are like hidden land mines, nearly impossible to see, and ready to blow you to bits (pun intended :-) without warning.
What you're basically saying is that you want semantics that's basically defined by the compiler vendor (or, more accurately, compiler/operating system/hardware trio), but you're pissed that the standard leaves it up to the compiler vendor as to whether or not you will get that option. You're already "at the mercy of the benevolence of [your] compiler vendor" to give you things like uint32_t, why is the presence of a -O0 inherently worse?
So yeah, I’m pretty happy to call this a “design bug” in the entire language. Those kinds of bugs are hard to fix, because you need the whole C++ committee to fix this, and we all know how bad design-by-committee performs.
So just switch to Rust :)