Comment by lelanthran

4 hours ago

> The point of the post is to say it's not possible to avoid them. Or at least, no human since the invention of C in 1972 has.

What are you talking about? UB was coined only in the first C standard, in 1989. Prior to that there was no "If you do this, anything can happen". It was "If you do this, that will happen".

More like, "if you do this, what happens depends on your particular combination of hardware, operating system, and compiler. Don't ask us."

  • No, that would be implementation defined.

    • No, that's actually UB. The important bit here is "compiler defined" -- UB means the compiler is allowed to assume it never happens while compiling.

      Consider, for example, an implementation defined function f() -- which can also diverge/crash horribly, etc.

      If I write

          if p {
            print("p is true")
          } else {
            g()
          }
      
          if p {
            f()
          }
      

      Then either we: - print p is true and execute f - do nothing

      This is true regardless of if f immediately crashes the computer, nasal demons, whatever -- that's implementation defined.

      UB means f may never happen.

      And that means the compiler may optimize this to just:

          g()
      

      Notice the difference here -- the print never happens!, and g always happens.

      You can see why this is concerning when you write code like

          if dry_run {
            print("would run rm -rf /")
          } else {
            run("rm -rf /")
          }
      
          if dry_run {
            // oops: some_debug_string is NULL and will segfault!
            print(some_debug_string);
          }