From Russ Cox
Lumping both non-portable and buggy code into the same category was a mistake. As time has gone on, the way compilers treat undefined behavior has led to more and more unexpectedly broken programs, to the point where it is becoming difficult to tell whether any program will compile to the meaning in the original source. This post looks at a few examples and then tries to make some general observations. In particular, today’s C and C++ prioritize performance to the clear detriment of correctness.
I am not claiming that anything should change about C and C++. I just want people to recognize that the current versions of these sacrifice correctness for performance. To some extent, all languages do this: there is almost always a tradeoff between performance and slower, safer implementations. Go has data races in part for performance reasons: we could have done everything by message copying or with a single global lock instead, but the performance wins of shared memory were too large to pass up. For C and C++, though, it seems no performance win is too small to trade against correctness.
My problem with C/C++ is the people behind the spec have sacrificed our sanity in the name of “compiler optimization”. Signed overflow behaves the same on every cpu on the planet, why is it undefined behaviour? Even more insane, they specify
intN_t
must be implemented via 2s complement… but signed overflow is still undefined because compilers want to pretend they run on pixie dust instead of real hardware.Great read! But yes, that’s pretty much the point of C/C++ 😂