Enumerating Core Undefined Behavior
open-std.org
open-std.org
I mean, I'll stick with C/C++ for now. I can write 'good enough' code which does what I expect and seems to be reliable. I just hate the feeling that without spending a truly ungodly amount of time on it, even the best code is peppered with unknown unknowns waiting to bite me at some critical moment.
Of course Rust still has plenty of undefined behaviour, it is just restricted to unsafe blocks. (There are occasional exceptions, such as the infamous floating point cast bug [1].)
I don't mind there being some UB (in fact sometimes it's necessary, especially as I eventually want to use it on embedded targets that need to do all sorts of weird memory jiggery-pokery). I don't even mind bugs; all software has bugs. What I want to move away from is a language which embraces widespread and subtle UB as a design philosophy.
Of course reducing and any kind of bug class is a plus, Rust is great, but I never had the feeling that my C++ code is more error prone than my Java or Python code just because some things are completely UB. What actually happens with UB is that the application crashes and/or data gets scrambled - I've yet to see my PC to feel free to stand up and walk away just because it was technically allowed to.
Agreed that generally once you've built and tested your code with a given compiler, I seem to be as reliable with C++ as I am with other languages. But if I can remove a whole class of reasons for me to have a really bad week, that seems like a winning move.
My point is that removing UB is like removing 1 deadly, 20 sickening, and 70 inconveniencing M&Ms. Which, by every metric, is a great thing. The only thing that bothers me is that some people act like removing UB is equivalent to removing all 10 deadly M&Ms, which obviously isn't the case.
What I worry about is the unreasonable (i.e. hostile) input.
https://stackoverflow.com/questions/16188263/is-signed-integ...
[0] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p090...
I really don't understand why WG21 is against this, do you happen to have a link to arguments against it? The only one I frequently see is that "it's faster that way" with a link to godbolt where iterating with a 32-bit signed integer on a 64-bit system is faster than iterating with a 32-bit unsigned integer, because the compiler exploits UB here to ignore overflow. Which is of course a completely useless example because simply using a correctly sized integer for iteration, signed or unsigned, will always result in the fastest most correct code.
I'm not aware of any other arguments against it.
“”” This direction was motivated by:
Performance concerns, whereby defining the behavior prevents optimizers from assuming that overflow never occurs; Implementation leeway for tools such as sanitizers; Data from Google suggesting that over 90% of all overflow is a bug, and defining wrapping behavior would not have solved the bug. “””
Just the other day I saw an article here titled "Rust Lang in a nutshell" and I was thinking, "Rust" and "in a nutshell" have become a contradiction in terms, what with all the language's complexity. But seeing this litany of UB in C++ puts that very much in perspective.
FWIW, I welcome this enumeration as a good overview but, wow, does it motivate me to consider alternatives.
Also there is an R1 version which hopefully will get discussed in the next meeting here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p170...