(no title)
HippoBaro | 1 year ago
UB is meant to add value. It’s possible to write a language without it, so why do we have any UB at all? We do because of portability and because it gives flexibility to compilers writers.
The post is all about whether this flexibility is worth it when compared with the difficulty of writing programs without UB.
The author makes the case that (1) there seem to be more money lost on bugs than money saved on faster bytecode and (2) there’s an unwillingness to do something about it because compiler writers have a lot of weight when it comes to what goes into language standards.
twoodfin|1 year ago
The real argument seems to be that C compilers had it right when they really did embody C as portable assembly, and everything that’s made that mapping less predictable has been a regression.
dathinab|1 year ago
Which I think is somewhat the core of the problem. People treating things in C in ways they just are not. Weather that is C is portable assembly or C the "it's just bit's in memory" view of things (which often is double wrong ignoring stuff like hardware caching). Or stuff like writing const time code based on assuming that the compiler probably, hopefully can't figure out that it can optimize something.
> The real argument seems to be that C compilers had it right when they really did embody C as portable assembly
But why would you use such a C. Such a C would be slow compared to it's competition while still prone to problematic bugs. At the same time often people seem to forgot that part of UB is rooted in different hardware doing different things including having behavior in some cases which isn't just a register/mem address having an "arbitrary value" but more similar to C UB (like e.g. when it involves CPU caches).
unknown|1 year ago
[deleted]
layer8|1 year ago
That’s not to say that it wouldn’t be worth it, but given the multitude of compiler implementations and vendors, and the huge amount of existing code, it’s a difficult proposition.
What traditionally has been done, is either to define some “safe” subset of C verified by linters, or since you probably want to break some compatibility anyway, design a separate new language.
zajio1am|1 year ago
Implementation-defined behavior is here for portability for valid code. Undefined behavior is here so that compilers have leeway with handling invalid conditions (like null pointer dereference, out-of-bounds access, integer overflows, division by zero ...).
What does it mean that a language does not have UBs? There are several cases how to handle invalid conditions:
1) eliminate them at compile time - this is optimal, but currently practical just for some classes of errors.
2) have consistent, well-defined behavior for them - platforms may have vastly different way how to handle invalid conditions
3) have consistent, implementation-defined behavior for them - usable for some classes of errors (integer overflow, division by zero), but for others it would add extensive runtime overhead.
4) have inconsistent behavior (UB) - C way
wyager|1 year ago
Whenever you do that, programmers deride the language for being "excessively academic" or something