Hacker News new | past | comments | ask | show | jobs | submit login

Perhaps, these days you're right -- assuming you want to only support mainstream architectures. These days you can mostly rely on all mainstream architectures to do something sensible with e.g. signed integer overflow[1] or excessive shifting, but that wasn't necessarily the case when most of C++ was standardized. As an example of a similar nature -- as I'm sure you know -- Rust has chosen to not abort/panic on signed overflow although almost all instances of such are most probably plain logic errors and could lead to security problems[2]. As far as I could understand, this was for performance reasons. Granted, this is not quite as disastrous for general program correctness as UB, but it can lead to security bugs.

Point being: Underspecification can give you a lot of leeway in how you do something -- and that can be hugely valuable in practice.

Just as an aside: Personally I tend to prefer safety over performance, but I was persuaded that UB is valuable by comments that Chandler Carruth of Clang (and now ISO C++ committee) fame made about UB actually being essential to optimization in C++. Sorry, can't remember where, exactly, those comments were made.

[1] Everybody's probably using two's-complement (for good reasons).

[2] Not nearly as easily as plain buffer overflows, but there have been a fair few of these that have been exploitable.




Even mainstream architectures don't handle excessive consistently, e.g. for shifting an n-bit integer, I believe some mask the shift by 2^n - 1, some by 2^(n+1) - 1, and some don't mask at all (i.e. 1 << 100000 will be zero). Of course, being UB (rather than just an "unspecified result" or some such) probably isn't the best way to handle the inconsistency.

In any case, I believe Rust retains many of the optimisations made possible via UB in C++ by enforcing things at a compile time. In fact, Rust actually has quite a lot of UB... that is, there are many restrictions/requirements Rust 'assumes' are true. For example, the reference types & and &mut have significantly more restrictions around aliasing and mutability than pointers or references in C++. The key difference between Rust and C++ is that it is only possible to trigger the UB with `unsafe`, as the compiler usually enforces rules that guarantee they can't occur. People saying "Rust has no UB" are usually implicitly meaning "Rust cannot trigger any UB outside `unsafe`".


Rust will actually now panic when not in release mode when an integer overflow happens, as opposed to how things used to be before, where it would just accept the overflow silently with wrapping semantics. Here is the discussion from when this change was announced: http://internals.rust-lang.org/t/a-tale-of-twos-complement/1...


Oh, that's good news!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: