7 ms·
That is a cop-out, and entirely useless definition of "correct". Why don't we call that what the compiler emits when it encounters undefined behavior not "corr
by captainmuon 9y ago
That is a cop-out, and entirely useless definition of "correct".
Why don't we call that what the compiler emits when it encounters undefined behavior not "correct" but "invalid" or "wrong"? It's a matter of changing the terms to not overload "correct". The compiler is free to output "invalid" code on "invalid" input - garbage in, garbage out. But to use the term "correct" is silly.
Going a bit further, I believe a compiler has the right to do sensible things with undefined behavior. I greatly prefer it to do the obvious thing, when it can't do the correct thing.
In this case, try to execute the function at the address given by Do; since Do is uninitialized just use the number already in memory at Do's location as an address. I would also not be surprised if it initializes it with 0, and places EraseAll at 0x00, and thus calls EraseAll (although I know that address spaces on modern computers do not work like that).
In reality, I would expect the program to crash most of the time with an access violation, rarely with an invalid opcode, and extremely rarely call one of the functions (when Do contains that address by chance).
- yorwba 9y ago> since Do is uninitialized just use the number already in memory at Do's location as an address. But the compiler has full control over that memory, and it's faster when the number is the same as what might eventually be written into it, but then you no longer need to write anything, since that value is already in memory, and now it's a constant and why keep a constant in memory when you can just inline it ... All of the steps are completely intuitive and a compiler capable of executing them is much better than one that just indiscriminately zeros all memory and never dares to optimize anything to avoid exposing someone's mistakes. The best a compiler can do in the face of guaranteed undefined behavior is to warn the programmer and tell them to fix their code. Unfortunately, C makes it quite difficult to distinguish between defensively-written code that avoids UB, and code that treats C like a portable assembler, that will do the "obvious" (but slow) thing.
- tom_mellior 9y ago> useless definition of "correct". Noting that your parent only used the word "correct" in the phrase "correct compilation"... > The compiler is free to output "invalid" code on "invalid" input ... you are actually agreeing with your parent. Maybe they should have said "legal compilation" instead of "correct compilation". You seem to be saying that your parent said "the resulting assembly program is a correct program", which is silly. We cannot talk about its correctness, as there is no specification to judge correctness against (or the source program already doesn't satisfy the specification, in which case the compiler cannot help and should never even be called before fixing the bug).
- captainmuon 9y agoI'm agreeing with the parent that the result is according to the spec. What I'm arguing is that we shouldn't call that a correct compilation. It is a wrong compilation - is wrong with prior notice, and there is in fact no way to do it right, because the source is wrong (UB). I think I don't disagree about behavior, but about semantics. We shouldn't say, e.g. in a compiler's manual, that the compiler is free to (has the right to, is correct to) do anything when it encounters UB. Rather, I'd warn that the compilation might fail silenty on UB. The difference is not factual, it is in tone. Stating matter-of-factly that nasal demons is the correct result of compiling UB code is aggravating. It is the equivalent of the compiler singing nana-nana-na-na (or ätsch bätsch for the Germans).
- tom_mellior 9y ago> Rather, I'd warn that the compilation might fail silenty on UB. What do you mean by "fail"? Terminate compilation without producing output code? That's not possible, the compiler cannot detect all (or even most) UB at compilation time. Or do you mean it would produce "wrong" code (as it does now)? That's not what is commonly called "failure", and I think putting it that way is obscuring the issue, not making it clearer.
- peoplewindow 9y agoYou're acting as if a compiler behaving reasonably is impossible. Yet Java compiles to code that runs basically as fast as C (modulo cases like where you use vectorised code in C and the JIT fails to auto-vectorise), but with rational and predictable behaviour in all cases. I suspect UB is going to seriously damage or largely kill off statically compiled languages in the long run. Speculating JIT compilers can compile code in such a way that all executions are defined yet which does not experience the speed penalty C programs suffer, because the optimiser is free to make risky assumptions that are checked on the fly and de-optimise if they fail. It's heavy to have a full blown compiler running at the same time as your app, but desktop/laptop machines tend to have spare cores doing nothing anyway, and on servers the compiler is only running for a short period during warmup anyway and then is hardly used again.