5 ms·
Yes it is, see x86 example in https://youtu.be/yG1OZ69H_-o https://youtu.be/yG1OZ69H_-o at about the 40 minute mark for a real world example
by kllrnohj 3y ago
Yes it is, see x86 example in https://youtu.be/yG1OZ69H_-o https://youtu.be/yG1OZ69H_-o at about the 40 minute mark for a real world example
- titzer 3y agoIt's actually really annoying to get an example from a video, but nevertheless... The example shows you still didn't really seem to grok my point, which I will state again. A compiler can introduce additional checks for overflow that guard a large region (e.g. the repeated code in that example plus the loop after--maybe even the whole function!) and then make exactly the same transformations in the guarded region. The result is exactly the same machine code. It will go fast and not go out-of-bounds or wrap around. If the program would go out-of-bounds or wrap around, the guard will dynamically catch than and branch to a slower copy of the code that does exactly the right behavior at the right place. This is exactly how Java JITs approach C code quality. They use all the same tricks, they just have to try harder to handle the edge cases. And besides, there are several other ways to get that code--instead of using int32_t, it could have been uintptr_t, which replaces UB with platform-specific behavior but nevertheless lets the compiler do the LEA and other addressing mode tricks. No need to resort to UB. The entire mindset of opening holes in the language specification to allow compilers to optimize without thinking hard is just wrong. Programs have bugs. They go out of bounds. Preserving the exact out-of-bounds behavior is what allows programmers to debug their code. Checking bounds is what keeps programs from getting pwned all the time. It's not an opportunity for magic go-fast at the expense of security and debuggability. We're here in this muck today because of a persistent and deliberate choice to be hostile to programmers, programs, and people running those programs because compiler designers didn't want to work hard. That doesn't fly in literally any other programming language domain; C is the odd duck and it's frankly ruined people's reasoning centers.
- kllrnohj 3y ago> The entire mindset of opening holes in the language specification to allow compilers to optimize without thinking hard is just wrong. I would counter that 2's compliment overflow is a worse design in practice as easily 99% of the time overflow happening at all is a bug. Rust almost got this right by making overflow be a panic in debug builds, but then they took the worst option in making it defined 2's compliment in release builds But also the mindset that everything must be extensively defined is just wrong. Nobody's standard library does this anyway, but also it's not feasible to do. You cannot define the exact outcome of data races, for example. UB is inevitable, it'll always exist in all languages. The debate is as such over where you put that line, not whether or not it exists at all
- titzer 3y ago> UB is inevitable There's a huge difference between UB (as in C/C++) and nondeterminism, so I don't accept this assertion. UB in C gives no semantics to executions containing it; it is neither spatially nor temporally contained. No other programming language has such a ridiculous and program- and programmer-hostile concept. And for good reason. It makes reasoning about buggy programs a non-starter. And all programs have bugs. We debug them by analyzing their runtime behavior! Crashing immediately upon a bug, exactly the same way on every machine, is the absolute best way to find and fix bugs that cannot be caught statically.