3 ms·
What the article misses is that the code wouldn't work on all hardware. Take MIPS for example, where the signed overflow would generate a hardware exception tha
by AlotOfReading 3y ago
What the article misses is that the code wouldn't work on all hardware. Take MIPS for example, where the signed overflow would generate a hardware exception that the OS might have implemented to do anything from nothing to killing the generating process.
C was never standardized solely on the basis of what's most performant. The vast majority of explicit UB is there because someone knew of a system or situation where that assumption wasn't true.
- lelanthran 3y ago> C was never standardized solely on the basis of what's most performant. The vast majority of explicit UB is there because someone knew of a system or situation where that assumption wasn't true. So? They could have called it implementation defined. The reasoning you present was broken then, as it is broken now. Your MIPS example displays no reason for UB to exist.
- AlotOfReading 3y agoImplementation defined means it has a defined behavior on every implementation. In the MIPS case defining that behavior would force the compiler to generate strictly signed instructions for signed values and define how the runtime platform handles these interrupts, rather than leaving the compiler free to generate "whatever works". Look, a lot of UB is frankly stupid and shouldn't be in a modern language spec, including signed overflow. I'm not defending that, only giving an example where you have to break compatibility to eliminate it.
- lelanthran 3y ago> In the MIPS case defining that behavior would force the compiler to generate strictly signed instructions for signed values and define how the runtime platform handles these interrupts, I respectfully disagree: in this particular scenario, it's enough for the compiler vendor to write "generates an interrupt on overflow" with no indication of what the handling should be, and still be well within implementation-defined behaviour. After all, the standard specifies what `raise()` does, and what `signal()` does, but doesn't specify how the runtime is going to handle `raise(signum)` when the program has not yet called `signal(signum, fptr)`. This scenario you presented displays exactly why UB should be replaced with IB in the standard. I've yet to see one good reason (including performance reasons) for why the dereferencing of a NULL pointer (for example) cannot be documented for the implementation. With UB, we have real-world examples of a NULL pointer dereference causing compilers to omit code resulting in a program that continued to run but with security implications. If changed to IB, the compiler would be forced to emit that code and let the dereference crash the program (much better).