Live data from Hacker News

Falsehoods programmers believe about undefined behavior

predr.ag

31–40 of 233 posts

Re: Falsehoods programmers believe about undefined behavior

#31

> 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. This one came as a surprise to me. Is this really (unconditionally) true? And if so, why? Seems trivial to me to ensure that UB that will never under any circumstance execute will not affect the functioning of an otherwise correct program.

The compiler may make optimization decisions based on the presence of UB so the code only needs to be present.

The compiler can't know that an arbitrary part of a function is unreachable if, for instance, that code path is controlled by a parameter or global state since that equates to solving the halting problem.

https://blog.llvm.org/2011/05/what-every-c-programmer-should...

Re: Falsehoods programmers believe about undefined behavior

#32
post #22

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…

> This is nonsense. The line with UB has to be reached for the execution to be undefined.

Check the footnote at item 14, it links to a page which shows one example of how a line with UB can be reached (basically: the optimizer can reorder the code so that parts of the line with UB will run much earlier than you'd expect).

Re: Falsehoods programmers believe about undefined behavior

#33

It is not explained why points 31 to 36 are valid, unlike HDL synthesis tools, C compilers are pretty deterministic, same input same output, except timestamps, etc. If an UB adopt X behavior one time, a reproducible build will take same X behavior the next time. Of course I am not negating the fact that this undefined in the first instance nor condoning the UB usage.

That is the observed behavior of the compiler not the defined behavior. (and while there’s some logical reason to assume that will likely continue to hold, the list is falsehoods programmers believe about undefined behavior, not observed behavior.)

"but it worked fine before" talks about the observed behavior

Re: Falsehoods programmers believe about undefined behavior

#34
post #22

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…

No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.

No, no, no. UB is a global property of your program. "All bets are off" even at compile time.

"Anything at all can happen; the Standard imposes no requirements. The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended."

https://blog.regehr.org/archives/213

Re: Falsehoods programmers believe about undefined behavior

#35

Earlier quoted context omitted.

That is the observed behavior of the compiler not the defined behavior. (and while there’s some logical reason to assume that will likely continue to hold, the list is falsehoods programmers believe about undefined behavior, not observed behavior.)

"but it worked fine before" talks about the observed behavior

Yes. That is the sub-category of “among all the falsehoods about UB, these are the falsehoods that can be categorized as [improper reliance on] OB”.

Re: Falsehoods programmers believe about undefined behavior

#36
post #22

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…

No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.

Out-of-order execution isn't the reason for this. The C standard assumes an abstract machine that allows OoOE, of course, but even with strict in-order hardware UB can hit you at any time, even before you'd think it could. That is because the C standard doesn't limit UB to any constraints like "following lines" or "subsequently executed instructions". Independent of the hardware, the compiler is allowed quite a bit of reordering of instructions. The standard just requires that (some) effects of those executions are ordered as written, but that doesn't include UB.

So if you have UB in your future path of execution, the compiler might just do whatever _right now_.

Re: Falsehoods programmers believe about undefined behavior

#37
post #22

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…

No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.

It still has to be executed by the abstract machine for the given set inputs for the whole execution to be undefined.

You are right that once the execution is undefined, you can't reason about the behavior. This includes ordering of side effects, or side effects od operations occurring before the line with UB.

But uttering UB in dead code making execution UB is utter nonsense. Otherwise any execution of any program that just utters __builtin_unreachable() would be undefined.

Re: Falsehoods programmers believe about undefined behavior

#38
post #22

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…

No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.

That's sounds plausible, but isn't. First of all, out-of-order execution has nothing to do with unreachable core - it just means that reachable code sometimes gets executed in a different order than the binary shows. It is speculative execution which can lead to unreachable code actually being executed.

However, even when processors execute code speculatively, they guarantee that no observable effects of executing that code will happen. So, if you have something like `if false {*NULL=7/0}`, the processor might attempt to execute that line speculatively, but it will revert any change it made, and it will not trap regardless of any other flags.

Re: Falsehoods programmers believe about undefined behavior

#39
post #22

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…

"The line with UB" becomes a very vague notion well before the program even executes. You can see this by dumping the disassembly of your program. The compiler can determine when values are defined and used and will emit code that satisfies the semantics of your program (according to the language specification). This often means that expressions within the same statement get evaluated at significantly different times, hoisted outside of loops, etc.

Re: Falsehoods programmers believe about undefined behavior

#40

> "If my program contains UB, and the compiler produced a binary that does X, is that a compiler bug?" It's not a compiler bug. True, if the language spec is the only thing in the universe you care about. But there are better and worse things compilers can do in the presence of UB, and the big one is warning you about it when it possibly can . There's another big discussion on the front page about signed integer over…

> there are better and worse things compilers can do in the presence of UB, and the big one is warning you about it when it possibly can. GCC should add -Wundefined-behaviour flag that will unconditionally print "warning: this program might or not have UB" as the first diagnostic.

It should also warn if there are infinite loops, so the dev can know whether it will ever halt.
Post reply on HN