Live data from Hacker News

Falsehoods programmers believe about undefined behavior

predr.ag

121–130 of 233 posts

Re: Falsehoods programmers believe about undefined behavior

#121

UB is not allowed in a constant expression in c++, which is a good reason to put constexpr in front of as many things as you can.

You need to actually invoke at compile time your constexpr function with the specific arguments that would cause UB to actually get an error.

It is not significantly better than running your test cases with with UBsan but it is a nice feature.

Re: Falsehoods programmers believe about undefined behavior

#122

It's surprising to see so much debate about when or where UB "happens". Unfortunately this article doesn't refer to the best tool to root out UB - UBSan. If you write C or C++, you should have a UBSan+ASan build that is configured to terminate with an error when it encounters violations. You'll save yourself a lot of hair-pulling later. Then you don't have to wonder about the nebulous topics like what "line" the UB "…

This is all fine and dandy, but UBSan and ASan are memory hogs that just won't fit in my single digit MB microcontroller. So the only way to run them is too use an emulator, and that means I cannot sanitize drivers.

Yeah they are and that's too bad. HWASan is another option that reduces the overhead but would only work on a core that had MTE (which your microcontroller is not as likely to have).

Re: Falsehoods programmers believe about undefined behavior

#123

It's surprising to see so much debate about when or where UB "happens". Unfortunately this article doesn't refer to the best tool to root out UB - UBSan. If you write C or C++, you should have a UBSan+ASan build that is configured to terminate with an error when it encounters violations. You'll save yourself a lot of hair-pulling later. Then you don't have to wonder about the nebulous topics like what "line" the UB "…

The UBSan+ASan combo is great! Rust's miri is another good one.

This post is already fairly long (~10min read) and I didn't want to make it any longer. It's also already getting flamed in predictable ways ("nonsense! UB has to be reachable to be a problem!") so I didn't want to add more ways to get flamed for it (:

(I'm the post's author.)

Re: Falsehoods programmers believe about undefined behavior

#124
post #109

I have a suggestion - it may be completely off the wall, but hear me out. C needs a mechanism to declare in a source file that certain behaviour must be defined, where that behaviour is undefined in the C standard but the target architecture behaves the defined way. Then, when the source is compiled on the target architecture it works as expected, but when compiled on something else it refuses to compile. For example…

I have almost no idea about C compilation but would it be possible with macros or somehow redefining int?

I don't think it'd be possible to get the compiler to treat unsigned integer overflow as defined using macros. But I'm not a subject matter expert.

Re: Falsehoods programmers believe about undefined behavior

#125

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

Code that represents UB doesn't have to be executed for the compiler to react to it.

More specifically, the linker, not the compiler.

The compiler has to respect DR 106. The linker, however, is allowed to write garbage into code.

Re: Falsehoods programmers believe about undefined behavior

#126

I have a suggestion - it may be completely off the wall, but hear me out. C needs a mechanism to declare in a source file that certain behaviour must be defined, where that behaviour is undefined in the C standard but the target architecture behaves the defined way. Then, when the source is compiled on the target architecture it works as expected, but when compiled on something else it refuses to compile. For example…

Suggestions like this are unfortunately quite infeasible (they fall under the hat of "define all the behaviors"), and the talk I linked in the post goes into why: https://www.youtube.com/watch?v=yG1OZ69H_-o

(I'm the post's author.)

Re: Falsehoods programmers believe about undefined behavior

#128

Earlier quoted context omitted.

The compiler isn't required to know if code is unreachable. For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). Or, here is a better example: for(int i=0; i > n;) { } *p=1; Here the compiler will assume that the loop ter…

> For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). No it won't. Otherwise all precondition checks would be meaningless. The compiler can only assume that it isn't null when fermats_last_theorem_is_wrong() is true. If…

That is not an infinite loop, it has an exit condition on i > n.

An infinite loop is not UB. It is well defined. Just the definition of a terminating loop is a bit funny.

> An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression, may be assumed by the implementation to terminate.

Plus:

> An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.

The compiler may only use as-if rule here if it can deduce the value is constant or limited. It can (but does not have to) assume the loop will end due to the conditional and lack of the other features. Which is still defined behavior. (since C11 at least, probably earlier)

Re: Falsehoods programmers believe about undefined behavior

#129

Earlier quoted context omitted.

Code that represents UB doesn't have to be executed for the compiler to react to it.

More specifically, the linker, not the compiler. The compiler has to respect DR 106. The linker, however, is allowed to write garbage into code.

the standard does not distinguish the linker from the compiler.

Re: Falsehoods programmers believe about undefined behavior

#130
post #113

I thought this was going to be an actually useful post about the details of UB, when it happens, and what it generally looks like, but instead it's just more of the same often repeated "if you write a program with UB your compiler will literally summon dragons and wipe your hard drive and kill you in your sleep." The truth is that practice diverges from theory, and, in practice, it is actually useful to talk about UB…

UB can easily wipe "the drive" on my microcontroller by sending a wrong SPI command to the flash chip, or by messing with write unprotected memory mapped built in flash. Welcome to kernel code. I believe one could make it play DOOM by clever malice in this case.

Yeah, I never said it couldn't, I said the more helpful thing to say is that UB can cause what looks like dead code to not be dead. If that dead code includes, an rm -rf, or, say, a function to enable/disable arbitrary pins on your chip, then yes, that dead code might be called, and with undefined parameters too. But saying UB will wipe your drive is just misleading and almost wrong.
Post reply on HN