4 ms·
If the change makes no difference at all, why do you think the change was made? Changes in specs are made because people lobby for them.
by quelsolaar 6y ago
If the change makes no difference at all, why do you think the change was made? Changes in specs are made because people lobby for them.
- klodolph 6y agoI think the relevant phrase is "so you must define what the behavior is in your implementation". With simple compilers, you could more or less define what happens with undefined behavior. For example, on platform X, if you dereference NULL, you get a segfault. On platform Y, you get a zero value. Problem is these behaviors are hard to define once you start thinking about the edge cases. You can dereference NULL with an offset, and once you do that, you might skip over any guard pages and overwrite a function pointer with garbage and then jump to some random location in memory, and once you do that, all bets are off. I mean, really, really off. So that leaves you with three options. 1. Abandon the idea of defining behavior in these cases. 2. Insert bounds checks. 3. Refine the idea of undefined behavior into two separate concepts--"bounded" and "critical" undefined behavior. C has taken all three options at the same time, in a sense. The main standard takes option #1, the Address Sanitizer gives you #2 (more or less), and annex L gives you #3. Annex L, option #3 above, is in many senses the sane option--but it requires a fairly large amount of work on the part of the compiler writers, and to my knowledge neither GCC nor Clang have implemented it. I would also like to add that some of the places where we see undefined behavior were inserted into the standard for real-world cases for unusual platforms. For example, the weird rules for pointer comparisons make sense when you think about segmented memory. Relational comparisons (<, >, <=, >=, but NOT == or !=) on pointers are generally used for traversing arrays, and if you have two pointers into the same array, it would be reasonable to assume that they have the same segment (depending on your memory model)... SO, you omit the segment comparison in this case.
- quelsolaar 6y agoI think there are valid reasons for a language spec to have Undefined behavior. But many UB in C would be much better if the where defined as platform specific. Like integer overflow, its very well defined on x86, ARM and every other CPU architecture in use, but not only does compilers act as if its unknowable, even when they clearly know it because they are implementing a known instruction set, they even make it hard to detect overflows since they optimize away tests since they cant happen.
- klodolph 6y agoI’d say that Annex L does get you closest to that goal, in that “bounded undefined behavior” can result in indeterminate values. > …not only does compilers act as if its unknowable… I disagree with this interpretation. The compiler is acting not as if it’s unknowable, but as if it doesn’t happen.
- MauranKilom 6y agoSurely you understand why compilers do this, right? This isn't compilers and standard writers being mean because they hate you. This is a language that you choose for speed being optimal for speed. In particular, signed integer overflow being UB was and still is a necessary evil so that compilers don't have to add ugly loop preambles to every loop you write.