1. 23
  1.  

  2. 3

    Just so I have this right,

    1. defer allows you to list out all of the actions that need to take place at the end of a scope.
    2. If there’s something wrong, even if you’re handling signals, a panic causes the deferred actions to be executed in the scope they’re defined and allow you to unwind until you hit a recover which returns 0 or 1.
    3. If 1 then the next statement in a non-panic normal operation is executed
    4. Otherwise the stack continues to unwind and execute deferred statements until another recover is hit or the program exits.

    This seems like a better error handling than the goto clean ups I would normally use for something similar. I don’t know though.

    1. 3

      The way you phrased #2 makes it unclear to me whether you understood or not, so I’ll try rephrasing.

      Deferred statements get run when you leave their controlling block, either normally or by panicking.

      panic causes all deferred statements to be run, LIFO.

      A defer can, but doesn’t need to, call recover().

      If recover is called while a panic is pending, it returns nonzero, the panic is canceled, and execution continues (the rest of the defer and then whatever comes after leaving that block — these aren’t resumable/continuable exceptions that can jump back to the place where the panic occurred).

      If recover is called while a panic isn’t pending, it returns zero, so you’re not expected to handle anything. And execution, of course, continues.

      If we panic and none of the defers on the stack call recover, crash.

      1. 2

        Oh and — if your defer calls recover and then discovers that it can’t actually handle the panic (either it got a different panic than it knows how to handle, or something went wrong in its attempt to fix things) it is allowed to re-panic. Calling panic before recover is forbidden since it would be an attempt to have two pending panics at once.

    2. 2

      Finally, C has been needing defer for a long time. As the paper says, this will definitely make it more usable and modern. After defer is added, we just need to add templates, namespaces, compile time expressions, references, concepts, and a larger standard library!

      1. 2

        defer would be nice. However I don’t really see why guard, panic and recover should be part of the proposal as well. Unfortunately the paper doesn’t really explain that.

        1. 1

          defer has to run when function exits, and a function can exit in two ways: via return, or via unwinding. Leaving unwinding undefined would be problematic*, and if you’re defining unwinding you may as well define basic functions to control it.

          *) Even though C doesn’t have exceptions per-se, it has longjmp that may be implemented via unwinding. It’s also very useful to have interoperability with environments that do use unwinding (C++, Windows SEH, Rust panics).

          1. 1

            I don’t really see why guard, panic, and recover should be part of the proposal as well

            The proposal itself answers your questions.

            1. 1

              I’m reading it, and I don’t see an answer to why they should be part of the proposal. There’s a section titled “Do we want a panic/recover mechanism?”, which goes into great deal about what a panic/recover mechanism is, but doesn’t answer the question of why we’d want it.

              Personally, defer would be ok, but I don’t want it panic/recover.

              In the end, what I want for new C standards isn’t a bunch of features. I want the removal of more undefined behavior. Maybe if it’s hard to support uniform behavior across all prrocessors, it could be made implementation defined. Paired with a description of suggested implementation defined behavior (“a boring implementation will do this, an exciting implementation has no constraints”), I think this could lead to a large improvement in the usability of the language.

              1. 2

                You can have defer without panic/recover (but it’s not very exciting, it’s just a bit of sugar). You can’t have panic/recover (in this style) without defer. So they’re linked in that way.

                1. 1

                  There’s a section titled “Do we want a panic/recover mechanism?”, which goes into great deal about what a panic/recover mechanism is, but doesn’t answer the question of why we’d want it.

                  The very second sentence of that section is:

                  The primary purpose of a panic/recover mechanism is error handling


                  defer would be ok, but I don’t want it panic/recover

                  I wouldn’t say I’m opposed to panic/recover, but I certainly find them a lot less interesting than defer.


                  I want the removal of more undefined behavior

                  Agreed. Much of the UB that’s there doesn’t make very much sense as UB, even from an optimization or portability perspective. E.G.

                  A nonempty source file does not end in a new-line character which is not immediately preceded by a backslash character or ends in a partial preprocessing token or comment (5.1.1.2)

                  In what situation is it interesting for that to be undefined?

                  1. 1

                    Why do you find defer by itself interesting?

                    1. 2

                      It removes the need for duplicated code or double free prone ‘goto error’.

                    2. 1

                      The primary purpose of a panic/recover mechanism is error handling

                      There are many mechanisms with a primary purpose of error handling. Why this one?