Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

221–230 of 503 posts

Re: Undefined behavior in C is a reading error

#221
Most of this discussion revolves around integer overflow.

Part of the problem is that most of the computer hardware is now twos-complement arithmetic. Programmers think of that as part of the language. It's not, for C. C has run, in the past, on

- 36 bit ones complement machines (DEC and UNIVAC)

- Machines with 7-bit "char" (DEC)

- Machines with 9-bit "char" (UNIVAC, DEC)

- Machines where integer overflow yields a promotion to float (Burroughs)

- Many GPUs provide saturating arithmetic, where INT_MAX + 1 == INT_MAX.

Go, Java and Rust have explicit byte-oriented models with defined overflow semantics, but C does not. C has undefined overflow semantics.

Many years ago, around the time Ada was being defined, I wrote a note titled "Type Integer Considered Harmful". I was pushing the idea that integer variables should all have explicit range bounds, not type names. As in Ada, overflow would be checked. Intermediate variables in expressions would have bounds such that the intermediate value could not overflow without the final result overflowing and being caught. Intermediate values often have to be bigger than the operands for this to work.

This never caught on, partly because long arithmetic hardware was rare back then, but it illustrates the problem. Numeric typing in programming languages addresses a numeric problem with a linguistic solution. Hence, trouble. Bounds are the right answer numerically, but force people to think too hard about the limits of their values.

Re: Undefined behavior in C is a reading error

#222

First: I do dislike how hard it is to avoid some UB / how impractical some of the rules are. But I also think a lot of discussions of this topic caricaturize compiler writers to a ridiculous degree. Almost describing them to write optimization passes looking for UB so they can over-optimize something, while cackling loudly in glee about all the programs they can break. The set of people doing so overlaps with the set…

The caricatures are somewhat accurate though, optimizations that look at UB adversarially are never anywhere close to justified. > The set of people doing so overlaps with the set of people complaining that the compiler doesn't optimize their code sufficiently to a significant degree. There's no contradiction here, and the overlap is generally just "people who care". The optimizations that are not safe shouldn't exis…

Name one such optimization. We'll be happy to refute your points for that one.

Re: Undefined behavior in C is a reading error

#223
The C standard is not the Bible, it is not written by an almighty god. As respectable K&R are, they are humans who wrote a standard for their own needs, based on the state of the art of that time. Sadly C is the work of mortals...

Reading the standard trying to understand the way of god like religious scholars do is a pointless exercise. Modern compiler developers found that exploiting undefined behavior the way we do new leads to interesting optimization, others found it reasonable so now it is the standard.

I think the issue most people have now is that compilers use advanced solvers that are able to infer a lot from undefined behavior and other things, so UB is no longer just "it works or it crashes".

Re: Undefined behavior in C is a reading error

#224

I think the problem is cultural in the C community. C programmers have Stockholm Syndrome around UB optimizations. As TFA notes, "There is No Reliable Way to Determine if a Large Codebase Contains Undefined Behavior" https://blog.llvm.org/2011/05/what-every-c-programmer-should... That's because UB is a bug that occurs as your program runs (e.g. dereferencing a null pointer). You'd have to prove that your program is f…

Good point. C programmers have come to assume that C is a shitty language with terrible semantics and it's their fault for not using Rust or something. They blame the language for the mess made by standards/compilers.

Re: Undefined behavior in C is a reading error

#225

Earlier quoted context omitted.

NPE isn't really a relevant comparison point - it raises an exception of sorts in both languages. Accessing an array past its end, accessing freed memory, reading uninitialized memory seem more apt.

These are all issues a compiler could insert checks for, saving you the time to do it manually, while trading performance for security or correctness. C doesn't trade performance away, so if you'd like to pay the price of these checks, it's on you, the programmer to add them in. C programmers have to put in extra effort to make the executables safer and output correct results. Other languages trade off performance fo…

C is designed to allow programmers to insert or remove checks as performance tuning. Compiler UB "optimizations" that remove that ability from the programmer make the language unusable.

Re: Undefined behavior in C is a reading error

#226
post #43

Earlier quoted context omitted.

When compiler writers have get "creative" with C undefined behavior, programming C no longer produces predictable results. > least disruptive Like starting to optimize away loop checks that can "never happen" because signed integer overflow is UB, suddenly changing the behavior of programs that were fine for years? I wish I could just fence off this insanity by never starting another project in C. Unfortunately, C is…

> Like starting to optimize away loop checks that can "never happen" because signed integer overflow is UB, suddenly changing the behavior of programs that were fine for years? Yeah. Not doing that on modern processors is actually quite disruptive. Here: for(i = offset; i What C compilers currently do is, in line with the standard, ignore the case that offset + 16 might overflow. This makes this eligible for loop unr…

This is a common argument, but it is flat out wrong. If, as claimed, compilers have complete freedom of choice about how to handle UB, they have the choice to e.g. make this behavior depend on the processor architecture. Compiler developers are choosing to use UB to make C semantics defective.

Re: Undefined behavior in C is a reading error

#227

Two points: The notion that compilers that encounter undefined behavior are allowed to generate any code they want is a new interpretation, for some value of "new". I can't remember the first time I encountered such an interpretation being used by compiler writers to justify something they wanted to do until sometime after 2000. The notion that John Regehr has (quoted in the article) that undefined behavior implies t…

The standard (in the prevailing reading of the UB section, and also in practice) places no requirements on the behavior of programs containing UB. None of the paragraphs you quoted have any bearing on how an UB-laden program behaves.

Re: Undefined behavior in C is a reading error

#228
post #173

Earlier quoted context omitted.

No, the C standard doesn't say that "undefined behavior can be ignored" (which would mean what, making it defined?). It says, "NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, ...". It doesn't say that the behavior can be ignored. It says that the undefinedness can be ignored. The implementation doesn't have to take notice of the fact that the behavior is unde…

"undefined behavior can be ignored" (meaning: the case where this could overflow need not be considered and can be treated as though it does not exist) vs "The implementation doesn't have to take notice of the fact that the behavior is undefined" strikes me as a distinction without a difference given that we land in exactly the same spot: the standard allows us to treat "for (int i=param; i > An implementation might…

Of course an implementation can do anything it likes, including defining the behavior. That's one of the infinitely many ways of handling it -- precisely because it's undefined behavior.

I'm not using "undefined behavior" as the English two-word phrase. I'm using the technical term as it's defined by the ISO C standard. "The construct has undefined behavior" and "this implementation defines the behavior of the construct" are not contradictory statements.

And "ignoring the situation completely" does not imply any particular behavior. You seemed to be suggesting that "ignoring the situation completely" would result in the loop iterating exactly 16 tyimes.

Re: Undefined behavior in C is a reading error

#229

I think one of the best attempts to solve this is the attempt to classify undefined behavior into "bounded" and "critical" UB, which is a distinction that hasn't gained as much traction as I'd like. Something like 1 Critical UB is stuff like writing to a const object, calling a function pointer after casting it to an incompatible type, dereferencing an invalid pointer, etc. Basically, anything goes. This is part of t…

> Something like 1That is what implementation-defined behavior is for. Feel free to advocate for changing the standard accordingly.

Re: Undefined behavior in C is a reading error

#230
post #180

Earlier quoted context omitted.

That's precisely my point? Because the overflow case is undefined, the compiler can assume it doesn't happen and optimize based on the fixed loop count.

The overflow case is not UB. param can be unsigned, of fwrapv may be declared. Or the compiler chooses to declare fwrapv by default. In no case is the compiler allowed to declare the overflow away, unless it knows from before that param can not overflow. The optimization on loop count 16 can still happen with a runtime guard.

If param is unsigned, then "param + 16" cannot overflow; rather, the value wraps around in a language-defined manner. I've been assuming that param is of type int (and I stated that assumption).
Post reply on HN