Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

51–60 of 503 posts

Re: Undefined behavior in C is a reading error

#51
post #4

The author seems to be missing this essential text: "the implementor may augment the language by providing a definition of the officially undefined behavior." Making a system call is undefined behavior in the C standard, but it's not undefined behavior in clang-on-FreeBSD, because the implementors of clang on FreeBSD have defined what those system calls do. Ditto for "asm" (UD unless/until you're running on a compile…

Neither system calls nor the asm keyword are undefined behavior in the sense that C uses the term. They are, simply put, not covered by the standard at all.

System calls--assuming you're referring to the C prototypes you call--work as normal external function definitions, just having semantics which are defined by the library (i.e., the kernel) and not the C specification itself. The asm keyword is a compiler language extension and is effectively implementation-defined (as C would call it), although compilers today tend to poorly document the actual semantics of their extensions.

Re: Undefined behavior in C is a reading error

#52

Earlier quoted context omitted.

Another thing is that the wording around some of the UB issues is just plain bad. The most extreme probably is the rules around strict aliasing. That there, for quite a while, was uncertainty whether the rules allow type punning by reading a union member when the last write was to another member of a good example of not taking reality into account. Yes memcpy exists - but it is even less type safe!

The union punning trick is UB in C89 and well-defined in C99 and later, although it was erroneously listed in the (non-normative) Annex listing UBs in C99 (removed by C11). Strict aliasing is another category of UB that I'd consider gratuitous.

> The union punning trick is UB in C89 and well-defined in C99 and later, although it was erroneously listed in the (non-normative) Annex listing UBs in C99 (removed by C11).

Right, that's my point. If the standard folks can't understand their standard, how are mere mortals supposed to?

> Strict aliasing is another category of UB that I'd consider gratuitous.

I'm of a bit split minds on it. It can yield substantial speedups. But is also impractical in a lot of cases. And it's often but strong enough anyway, requiring explicit restrict annotations for the compiler to understand two pointers don't alias. Turns out two pointers of the same (or compatible) type aren't rare in performance critical sections...

Realistically it should have been opt-in.

Re: Undefined behavior in C is a reading error

#54
Commenters here seem to be missing the core thesis of this article. It's not about what the standard literally means; it's about it's spirit -- and the reason for its spirit.

The issue is "undefined behaviour" should never have been interpreted this extremely. The standard may be silent on how extreme, but it is implausible to suggest that the standard was actually written to enable this.

Compiler writers for C! dismiss severe issues which occur in compiling any program with undefined behaviour; issues which would render any modern language a bad joke.

Compiler writers are using this as a perverse shield to simply fail to optimize for correctness, or provide means to; and to enable them to optimize only for performance.

Are we really saying the standard supports this sleight-of-hand? It seems more like using the Second Amendment to murder someone.

Re: Undefined behavior in C is a reading error

#55
post #3

If C is just a portable assembler then what if the assembly itself has undefined behaviour. :)

I seem to recall that Intel and AMD CPUs will behave in strange and unusual ways, particularly when it comes to things like bitshift op flags, if you shift by out of range values, or by 0 or 1. So I guess undefined behaviors in C are somewhat consistent with CPUs. But as other people mentioned Intel is much more forgiving than X3J11. If you ever wanted to find all the dirty corner cases that exist between ANSI and hardware, I swear, try writing C functions that emulate the hardware, and then fuzz the two lockstep style. It's harder than you'd think. [don't click here if you intend to try that: https://github.com/jart/cosmopolitan/blob/master/tool/build/...]

Re: Undefined behavior in C is a reading error

#56
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 free of bugs to prove that you won't encounter UB at runtime, which is not possible in general.

But C programmers believe they deserve to be abused this way.

"Sure, the C compiler is allowed to nuke your entire program whenever there's a bug at runtime, but all you have to do is prove that your program is bug free! Why, any real C programmer can write bug-free code, so if you have any UB bugs, you're probably not good enough to write C. Sure, I've been bruised by UB bugs in the past, we all have, but when I made those mistakes, I deserved to be bruised, and those bruises made me a better programmer."

Re: Undefined behavior in C is a reading error

#57
post #42

> license for the kinds of dramatic and unintuitive transformations we’ve seen from the compilers, and any indication that undefined behavior should be a vehicle for permitting optimizations. Does anyone have an example of a time where Clang or GCC actually did something bad upon witnessing undefined behavior, rather than simply doing nothing, as the standard proposes? I ask because every time I've seen people get ma…

The types of surprises that I've seen have to do with inferences that the compiler draws: this program would be undefined if foo was negative, therefore foo is not negative, therefore I can optimize away this condition.

Re: Undefined behavior in C is a reading error

#58
post #32
post #19

Earlier quoted context omitted.

Are you arguing that e.g. Turbo C and friends from the 80s were higher quality than modern C compilers?

I believe he’s arguing that they were more sane/pragmatic compilers — they would be inherently less comfortable exploiting UB to do anything other than what people expected or were used to, because there is more real possibility of retribution (GCC could get away with making demons fly out your nose and just lose marketshare [that it doesn’t directly depend on anyways] where a commercial compiler would go out of busi…

> I believe he’s arguing that they were more sane/pragmatic compilers

I can’t imagine they have any actual experience with Borland or Symantec’s C or C++ compilers, then. These things had notoriously shakey standards compliance and their own loopy implementations of certain things, along with legions of bugs – it’s not hard to find older C++ libs with long conditional compilation workarounds for Borland’s brain damage. Microsoft’s C++ compiler was for years out of step with the standard in multiple ways.

Part of the reason GCC ate these compilers’ markets for lunch was the much more rigorous and reliable standards adherence, not just the lack of cost.

This reads like nostalgia for an age that never was.

Re: Undefined behavior in C is a reading error

#59
post #24

I think the real problem stems from the mismatch between modern processors and the processors C was originally designed for. C programmers want their code to be fast. Vanilla C no longer gives them the tools to do that on a modern processor. Either the language needs to be extended or the compiler needs to get more creative in interpreting the existing language. The latter is the least disruptive and it doesn't stop…

> Vanilla C no longer gives them the tools to do that on a modern processor

Can you elaborate on this point?

Re: Undefined behavior in C is a reading error

#60
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 1Critical 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 the "analyzability" optional extension which I wish would gain more traction.

Post reply on HN