News for hackers. Stuff that matters.
Re:Three new utility functions in C++23 by assbuttbuttass on Wednesday November 09, 2022 @08:01AM (#33530949)
It's undefined behavior. The compiler is free to do whatever, including making your program more broken.
Re:Three new utility functions in C++23 by fluoridation on Wednesday November 09, 2022 @08:06AM (#33531008)
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.
Re:Three new utility functions in C++23 by carstimon on Wednesday November 09, 2022 @08:17AM (#33531141)
Undefined 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.

Re:Three new utility functions in C++23 by afiori on Wednesday November 09, 2022 @08:21AM (#33531187)
I suspect you meant to omit the `if (c == 'd')` part in the last example
Re:Three new utility functions in C++23 by mannykannot on Wednesday November 09, 2022 @09:44AM (#33532265)
I 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.

Re:Three new utility functions in C++23 by randomNumber7 on Wednesday November 09, 2022 @06:27PM (#33539691)
I get your point, but assert is usually removed in release builds. Abort would probably be better if you want to crash the program.
Re:Three new utility functions in C++23 by mattkrause on Wednesday November 09, 2022 @11:00AM (#33533485)
I find it unhelpful to frame undefined behavior as an “escape hatch” that lets the compiler do anything it wants. Compiler writers aren’t gleefully hunting for issues and using its presence as an excuse to make your life miserable.

Instead, the weirdness arises because the compiler makes certain assumptions and transforms the code in ways that depend on them. For example:

1. Null pointers are never dereferenced.

2. Ptr *p is dereferenced.

3. p therefore cannot be null.

4. Ergo, we can omit checking whether p is null.

If the initial premise isn’t actually true (i.e., you slip up and dereferenced a null pointer), the chain of logic breaks down and boom! Applying many such rules can certainly lead to weird emergent behavior—and maybe you should act as if anything can happen—but it’s not a total free-for-all.