4 ms·
The correct reasoning would be: “Because it’s undefined, it won’t happen, that is, the code will never divide by zero. Therefore, the divisor is non-zero or th
by comex 9y ago
The correct reasoning would be: “Because it’s undefined, it won’t happen, that is, the code will never divide by zero. Therefore, the divisor is non-zero or the division is never executed.”
Undefined behavior can ‘go back in time’, but only to a point where the compiler can prove it will necessarily occur in the future. And there’s no language in the standard allowing compilers to assume that an arbitrary function will ever return, as opposed to terminating the program or entering an infinite loop.
There are some cases where the compiler is allowed to assume a loop will eventually terminate (one of the less widely known forms of undefined behavior), but only if the loop has no input/output or other observable effects besides spinning:
https://stackoverflow.com/questions/16436237/is-while1-undefined-behavior-in-c https://stackoverflow.com/questions/16436237/is-while1-undef...
Edit: And according to the linked Debian bug report thread, the problematic optimization could no longer be reproduced on newer versions of GCC.
- saagarjha 9y ago> Undefined behavior can ‘go back in time’, but only to a point where the compiler can prove it will necessarily occur in the future. I don't quite get what you mean here. If the compiler can prove that you perform undefined behavior, isn't it legal for it to move it to the start of the program and literally produce no output?
- cesarb 9y ago> If the compiler can prove that you perform undefined behavior, isn't it legal for it to move it to the start of the program and literally produce no output? Yes, it can! (Or worse, like making it erase all your files.) But that's only if it can prove that the program will always reach the undefined behavior. The path a program takes can depend on its input, command line parameters, contents of the filesystem, or even the phase of the moon (literally: the program can ask the operating system for the current date and time, and branch on a value derived from them). If a program will only reach undefined behavior once in a blue moon, the compiler is not allowed to output an executable which will fail when ran on dates which are not considered a blue moon.
- comex 9y agoYep. In the ereport() example, though, it’s even simpler: the program couldn’t execute undefined behavior given any input, because ereport() calls abort() if the error level is ERROR (as is the case here). There’s a statement syntactically following the ereport() which would be UB if it were executed, and since ereport isn’t marked noreturn, the compiler can’t prove that it won’t be executed. But that’s not the right standard: the optimization is only justified if the compiler can prove that it will be executed (under the assumption that control flow has reached the code whose observable behavior is being altered). Edit: that is, with any input that causes it to be altered. The most famous cases of UB involve compilers removing code entirely or optimizing an expression to a constant, but it’s just as valid (and more useful) to replace one computation with another computation (e.g. an unsigned division with a signed division) that produces the same result for “legal” inputs, but potentially a different result for “illegal” inputs – where “illegal” means “given that input at that point in the program, the program necessarily has executed or will execute UB”. From the standard’s perspective, the question is not which instructions are generated or what computations are actually performed, but whether the observable behavior is the same “as if” the computations in the source code were performed, for all execution traces not containing UB. (Just to reword myself in increasingly verbose fashion.)