46 ms·
Nonsense. The standard literally doesn't bind us in any way whatsoever. UB means there are no rules, anything goes. If the compiler is free to make demons fly o
by dale_glass 3y ago
Nonsense. The standard literally doesn't bind us in any way whatsoever. UB means there are no rules, anything goes. If the compiler is free to make demons fly out of my nose, it's equally free to produce a nice error message to the effect of "Don't do that".
I'd much prefer if the standards people started defining every possible instance of UB as a fatal error or as an implementation defined behavior, but that's not strictly required.
- layer8 3y agoSome instances of UB are data-dependent, and some would require solving the halting problem to statically distinguish them from non-UB. What you propose is therefore not generally possible at compile time, and at runtime only with considerable performance impact.
- weinzierl 3y agoThanks for pointing that out. Detecting UB is hard and sometimes impossible in C and C++. If you design your language accordingly you can avoid that. At least I think that is how Rust deals with it, but I'm happy to be convinced otherwise.
- coliveira 3y agoIf some form of UB is impossible to detect, then the compiler cannot do anything about it either, making the whole debate useless. Any action taken by a compiler relating to UB must be for some cause that is detectable at compilation time.
- layer8 3y agoThat’s not quite true, the compiler could add code to detect all UB at runtime, and then abort or whatever. It’s just that this would also pessimize UB-free code, and most compilers opt to not do that, at least in release mode.
- weinzierl 3y agoThat is not true and very important to understand. The optimizations a compiler does by eliding UB stuff are often very effective and I think no one in the thread has questioned that. It is a fallacy, though, to think that these optimizations could be replaced by diagnostics. That would be hard in most cases and sometimes impossible.
- dale_glass 3y agoSo fix it to the extent possible. Eg, this: https://t.co/Z1Ib2fIyu6 https://t.co/Z1Ib2fIyu6 Is easily fixable. A. static Function Do; -- This is a syntax error, initialization is mandatory. B. It's initialized to nullptr, and compiled to jmp 0x0
- layer8 3y agoYes, you can fix it in some cases, but the real errors usually happen in complex code where it is much harder or impossible to detect at compile time. The examples in TFA are very simplified for exposition purposes, they are not representative of ease-of-detection.
- dale_glass 3y agoI don't see how this particular case could ever be hard to deal with. Using uninitialized memory is UB, so initialize every byte of memory allocated to NULL. Dereference NULL pointers as-is. Done. I'd be quite happy with a best effort approach. If you can't be perfect in every case, at least handle the low handling fruit.
- layer8 3y agoThis approach would also impact UB-free code that initializes the memory later. C compilers don’t want to pessimize such code. The difficulty lies in identifying only code with actual UB.
- dale_glass 3y agoThat's perfectly fine with me. If the compiler can prove the code is initialized twice, then it's free to deduplicate it. Otherwise I'll happily eat the cost and preserve more of my sanity when debugging.
- layer8 3y agoYou’ll happily eat the cost, but the target audience of C compilers traditionally doesn’t. That’s the point made by TFA. C prioritizes performance over safety.
- weinzierl 3y agoI agree with you more than you think. "if the standards people started defining every possible instance of UB as a fatal error or as an implementation defined behavior," We can wish for that, but it does not and never will. Writing C or C++, first and foremost, means writing code against the standard and we have to deal with what the standard says. Of course we are free to give up on the standard and target a particular implementation of C or C++ in a particular compiler. If you also like to to call that writing C or C++ I would not argue with you. It is still a very different thing because you give up the primary advantage of C and C++ that you can compile basically everywhere. My point now is that if you give that up it makes no sense to stick with C or C++ in the first place and in this day and age.
- dale_glass 3y ago> My point now is that if you give that up it makes no sense to stick with C or C++ in the first place and in this day and age. You wouldn't be giving anything up. The standard defining something as UB means you absolutely shouldn't be doing that. So a compiler doing something defined in case of UB can't harm you in any way, and doesn't deviate from the standard, because the standard prescribes no rules in the case you're invoking.
- weinzierl 3y agoWith giving up I meant giving up portability by targeting a particular implementation of C or C++ in a particular compiler. The standard is what it is and discussing a hypothetical standard is moot.
- dale_glass 3y agoYou don't give up any portability. If the standard says that say, dereferencing a NULL pointer is UB it means you're not supposed to do that ever, on any OS or compiler. A compiler can choose to do something sensible like producing a fatal error message without any downside, since per standard that's not ever supposed to happen anyway.