3 ms·
> Although lots of things blow up (and a few of them literally) due to overflow, very few blew up because it was UB, most of them blew up because it was overflo
by Asooka 5y ago
> Although lots of things blow up (and a few of them literally) due to overflow, very few blew up because it was UB, most of them blew up because it was overflow
The real problem is when a compiler deletes code due to UB. The poster example being that you can't check for overflow by adding two numbers and examining if overflow occurred, since overflow is undefined. Strict aliasing can similarly break specific memory management code, because it often has to juggle raw memory and an unfortunate inlining can produce a function where a pointer exists simultaneously as two different incompatible types. Another favourite of mine is the fact you can't check if a reference in C++ is null, because it can't be, even though it can happen. The compiler just deletes code like "if (&x)".
This all happens silently, and only with full optimisations, making it possibly the worst footgun in all of C and C++, and it's not even the fault of the language, but a choice by the implementers.
At work we just don't write standard C, we use -fwrapv, -fno-strict-aliasing and a couple of others. Writing software at scale is simply impossible with UB looming over your head all the time.
- MauranKilom 5y agoCould you point out what (legal, UB-free) way exists to obtain a null reference in C++? If it requires UB elsewhere for the expression "if (&x)" to make any sense, I don't see why this is something you blame the compiler implementer for.
- a1369209993 5y ago`memset(&some_struct,0,sizeof some_struct);`, for starters. I don't know (or care) if some random chunk of the C++ spec says that's disallowed, but it happens in quite a lot of working code. I also use `if(!this) return PLACEHOLDER;` (in non-virtual methods) a fair bit, which amounts to the same thing: C++ says it never happens, C++ is wrong as a matter of observed fact.
- ncmncm 5y agoAll it takes is X& x = *p; // p might be 0. Y& y = p->y; It is the responsibility of whoever made the reference not to dereference a null pointer when initializing it. In the second form, it wouldn't help if you could check for a null &y, because it (probably) wouldn't be null anyway.
- tialaramex 5y agoRight but the post you're replying to asked for any way to do this without invoking Undefined Behaviour. If p is a null pointer, dereferencing it is Undefined Behaviour and you lose immediately.
- Asooka 5y agoIt's fairly trivial to make one by dereferencing a pointer that just happens to be null based on user input, which the compiler can't check. There are several acceptable ways for the compiler to deal with it: 1. Require the programmer to prove to the compiler that the pointer is not null. 2. Insert null checks and abort the program if the pointer is null. Both of those are deficient for me, because it's possible for some other bug to cause the memory holding the reference to be overwritten with 0, so I really favour: 3. Treat references as immutable pointers that can be null, but disallow creating them from pointers that are obviously constantly null. Obviously currently all ways to obtain a null reference are UB, but at the same time the compiler happily produces a program that creates a null reference, but deletes the check for it. Which is the absolute worst possible way to do it. It's a needless optimisation that requires you to solve the halting problem to be safe.