3 ms·
If you have undefined behavior, your program is already broken. No such thing as "more broken"; there's already no theoretical limit to what might happen if it
by fluoridation 4y ago
If you have undefined behavior, your program is already broken. No such thing as "more broken"; there's already no theoretical limit to what might happen if it gets triggered.
- carstimon 4y agoUndefined behavior is considered worse than crashing, which is typically the alternative when reaching "unreachable" codepaths. Compare these two blocks similar to the article switch (ch) { case 'a': do_a(); return; case 'd': do_d(); return; // ch is guaranteed to be 'a' or 'd' by previous code. default: assert(0); } switch (ch) { case 'a': do_a(); return; case 'd': do_d(); return; default: std::unreachable(); } If the programmer is wrong about `ch` in the first one, the program terminates. For the second one, the compiler could change it to be equivalent to if (ch == 'a') { do_a(); } else { do_d(); } return; If the programmer is wrong here, the program might `do_d()` with unintended consequences. I'd say "going down unintended codepaths" is typically considered worse than crashing. N.b. fixed last code example- thanks afiori.
- randomNumber7 4y agoI get your point, but assert is usually removed in release builds. Abort would probably be better if you want to crash the program.
- afiori 4y agoI suspect you meant to omit the `if (c == 'd')` part in the last example
- mannykannot 4y agoI take your point, but you can get the behavior of your first example, while still marking the default branch with std::unreachable(), by asserting the preconditions before the switch. This seems to me to be a pretty general equivalence. So what does std::unreachable() do here? In this particular case, and with NDEBUG defined and any level of optimization selected, I suspect that, at a minimum, the switch would be replaced as you have shown in all versions - it would take a more complex example to show how std::unreachable() makes a difference. The point is, now we have a choice - and it is one that is being offered without creating any backwards-compatibility issues. Furthermore, the original function, without assertions, is not guaranteed to crash, with or without std::unreachable(). You need some explicit checks to get a desirable response in the case where a mistake has been made, and that option is just as available whether or not you use std::unreachable(). Therefore, while I agree you have shown that not all broken variants of a given program are equivalent, this does not show that std::unreachable() is harmful.