Live data from Hacker News

Falsehoods programmers believe about undefined behavior

predr.ag

131–140 of 233 posts

Re: Falsehoods programmers believe about undefined behavior

#131

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…

That mechanism exists: inline asm.

As for your example, unsigned overflow is already defined in C and C++ and you can force the compiler error for non-32-bits using a static_assert.

Re: Falsehoods programmers believe about undefined behavior

#134

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

He's not trying to define all behaviours, he wants a static assertion that the compiler will compile certain behaviours in a specific way. Seems very different.

Re: Falsehoods programmers believe about undefined behavior

#135
post #116

Earlier quoted context omitted.

If it would result in different behavior in the event of an overflow (which I think is generally not the case), then no. A typical for loop (using <) can easily been seen to not overflow, so this is a rare case anyway. Loops using signed comparison with <= where the compiler can't rule overflow out should result in a compiler or linter warning.

The inequality argument would seem to apply only to for loops with constant iteration counts, yeah? The compiler can't know that "i (wrong) I am not an expert on compiler optimization, but having reasoned through a few cases where a compiler is _unable_ to correctly make an obvious-seeming optimization, I tend to think that compiler writers have good reasons for the things they want to be able to assume.

If "i" started out higher than "n", the loop would exit immediately and there would be no increment. More generally, if "n" is an int, then even if n is modified each iteration, the "i If there were good reason for wanting to assume this, I would expect someone to have presented it; responses I hear just take the form of a single (usually contrived) example where more performant code is generated, then insisting that all other factors (e.g. being predictable/unsurprising, acting like the underlying architecture, mitigating bugs) are irrelevant. Just as GP did.

Re: Falsehoods programmers believe about undefined behavior

#136

Divide by zero was one that I always believed would give segmentation fault…but that is totally not the case; I’ve gotten Infinity as a return once… I forget what compiler gives what…

Javascript?

Ah, I did not specify; with GCC… I believe it was compiling as C vs C++

Re: Falsehoods programmers believe about undefined behavior

#137
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…

You have to understand that in the modern understanding of UB as applied by compiler writers, the compiler has every right to assume the program never triggers UB. This means that lines which would be UB if a variable had certain values can be used as proof that the variable doesn't have those values, thereby eliminating checks. For example, if a program looks like this: void foo(int* const p) { if (p!=NULL) { bar(p)…

[deleted]

Re: Falsehoods programmers believe about undefined behavior

#138
post #116

Earlier quoted context omitted.

The inequality argument would seem to apply only to for loops with constant iteration counts, yeah? The compiler can't know that "i (wrong) I am not an expert on compiler optimization, but having reasoned through a few cases where a compiler is _unable_ to correctly make an obvious-seeming optimization, I tend to think that compiler writers have good reasons for the things they want to be able to assume.

If "i" started out higher than "n", the loop would exit immediately and there would be no increment. More generally, if "n" is an int, then even if n is modified each iteration, the "i If there were good reason for wanting to assume this, I would expect someone to have presented it; responses I hear just take the form of a single (usually contrived) example where more performant code is generated, then insisting that…

Ah good point re the inequality, over thought it.

If there weren't good reasons for making the assumptions that modern compilers do, I'd have expected users of C and C++ to have converged on a more conservative compiler, at least in some significant number.

Re: Falsehoods programmers believe about undefined behavior

#139

Earlier quoted context omitted.

> 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,…

> An infinite loop is not UB. It is well defined.

From C11:

> An iteration statement whose controlling expression is not a constant expression,156) 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-3, may be assumed by the implementation to terminate.157)

> 157)This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven.

This makes infinite loops UB unless they fall under one of these exceptions (constant controlling expression, performs I/O, accesses volatile objects or atomics).

Re: Falsehoods programmers believe about undefined behavior

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

We need a doomcc that will replace all undefined behavior with doom. A more fun version of ubsan if you will.
Post reply on HN