Live data from Hacker News

Falsehoods programmers believe about undefined behavior

predr.ag

41–50 of 233 posts

Re: Falsehoods programmers believe about undefined behavior

#41

I am always amazed by articles like these. This guy thoroughly covers this topic. I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Is this just an interesting topic or do people actively push the compiler to see what it will do? Maybe I am a boring/simple programmer. :)

I wouldn't call some cases of UB like overflowing a signed int or running into a dangling reference "actively pushing the compiler". I'm having a hard time believing you didn't ever run into these or similar issues having "programmed for a long time".

For other cases (e.g. aliasing, alignment), I'd agree that one is rather safe as long as the dangerous tools (e.g. reinterpret_cast) are not used.

Re: Falsehoods programmers believe about undefined behavior

#42

Earlier quoted context omitted.

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

UB is typically a property of the execution of a program. A program may bump into UB for one set of inputs, but not for an other set.

Re: Falsehoods programmers believe about undefined behavior

#43

I am always amazed by articles like these. This guy thoroughly covers this topic. I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Is this just an interesting topic or do people actively push the compiler to see what it will do? Maybe I am a boring/simple programmer. :)

It's the same for me. Well, I've hit segfaults when dereferencing invalid pointers (including NULL). I've had some surprises with shifting and signed integers as well. But I'm not sure that I've hit strange behaviours late in development. All that stuff is just, oh, I got that wrong, let's fix it. At most - oh I hadn't known that detail about signed arithmetic.

If the compiler removes an important check or branch like in the post, and it isn't noticed in development chances are the code is dead, or not that important. And I'm not saying this to downplay the risks. A big risk is that a particular instance of UB is exploited only by a newer version of the compiler, after the code is already finished. But in general, the language remains a remarkably productive one that lets me get very close to where I want to be, very quickly.

Is it possible to know for sure that it's all correct and will continue to be correct with newer compilers? Not 100%, but maybe it's still a good tradeoff in some environments.

Re: Falsehoods programmers believe about undefined behavior

#44
post #6

The biggest problem with UB, as interpreted by C/C++ compilers is the unfounded belief that the spec says that you can assume any path that leads to UB is defacto incorrect and can be ignored. That's the bogus logic required for steps 13-16 to be true. That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - w…

This is an absurd reduction of the current situation.

> That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work without falling afoul of their invented nonsense.

I've never heard of anything like this, have you any sources for this happening?

Re: Falsehoods programmers believe about undefined behavior

#45
post #15

> 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.

No, it isn't. The line with UB has to be reached in the execution for the execution to be undefined.

Yes, but there is more to it: The compiler may assume that UB will never happen intentionally and optimize out the branch containing UB.

Re: Falsehoods programmers believe about undefined behavior

#46

> 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.

This [0] is the linked article for that point, I don’t do systems programming, so I can’t say I understand if this is trivial or not ;)

[0]: https://www.ralfj.de/blog/2020/07/15/unused-data.html

Re: Falsehoods programmers believe about undefined behavior

#47
post #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).

UB "making dead code live again" is not an example of UB in dead code making the execution undefined.

Yes UB in live code can have surprising effects, including executing dead code.

Re: Falsehoods programmers believe about undefined behavior

#48

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.

> C compilers are pretty deterministic, same input same output, except timestamps, etc.

"Sometimes gcc will opt to use a randomized model to guess branch probabilities, when none are available from either profiling feedback (-fprofile-arcs) or __builtin_expect. This means that different runs of the compiler on the same program may produce different object code." (from the gcc manual)

Re: Falsehoods programmers believe about undefined behavior

#49

I am always amazed by articles like these. This guy thoroughly covers this topic. I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Is this just an interesting topic or do people actively push the compiler to see what it will do? Maybe I am a boring/simple programmer. :)

> I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time.

Assuming you're working with C or C++, you've never:

- Dereferenced a pointer? - written a loop with a signed index? - Accessed an index in an array or a vector? - Used a variable? - Used an optimising compiler?

Compilers use undefined behaviour in all of the above scenarios as much as possible, and to do what you likely intended. That's not to say _all_ UB is as reasonable, but a significant amount of what you write relies on some implicit assumptions about UB for a compiler to output reasonable code.

Re: Falsehoods programmers believe about undefined behavior

#50

Earlier quoted context omitted.

That's from the spec POV. On x86 for example, signed int overflow is well defined.

That's irrelevant. A C compiler targetting x86 has no obligation at all to handle signed integer overflow in the same way the processor natively does. Because it is not an assembler - it is compiling against the theoretical C virtual machine. This is for the same sort of reason that unsigned overflow does have a well defined meaning in C, and will always do exactly that even for targets that do not natively do that (…

> A C compiler targetting x86 has no obligation

It kinda has an implied obligation to not screw with its users. And doing the same optimizations to fold bloated Cpp templates properly messes with my C code.

Post reply on HN