6

I have some code that I've inherited from someone very clever where they like to use gotos to leave the try block, jumping completely around the catch blocks.

It definitely works, and I suspect this is legal (I think that the C++ standard says that on exit from a scope, everything gets cleaned up properly, and I assume that applies to whatever the compiler had to do to implement exceptions on my platform).

Is this really legit? It's NOT something I'd ever write (it's too clever by half), but it's clearly working, and I just want to understand why this is OK.

Michael Kohne
  • 11,888
  • 3
  • 47
  • 79

4 Answers4

12

It can be legit and it depends on what the code does. For example I have written code that jumps out of a catch block, and it's used in a language's runtime library (for simplicity, the code that uses the runtime library does not implement the itanium exception handling, but is implemented using longjmp/setjmp). The runtime library however, through the C++ exceptions, does use it; and a mechanism is needed to cleanly transfer control between them.

try {
  doSomethingThatMayFail();
} catch(DiagnosticException&) {
  goto unwind;
}

if(0) {
unwind:
  longjmp(&lastSafePoint, 0);
}

I put this into a macro so that it's very convenient to write. The goto here is necessary to cleanup resources allocated during exception handling of the diagnostic exception.

As always, don't say "NEVER use this feature". Every use must be carefully thought about, instead.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    This might be a dumb question... but why could you not have `longjmp(&lastSafePoint, 0);` in the catch statement? – andre Jul 12 '12 at 19:19
  • 1
    @ahenderson because it would skip the cleanup code that the compiler emits when code leaves the catch block (the object that was thrown by a called function is usually allocated on the heap, and needs to be freed by someone). – Johannes Schaub - litb Jul 12 '12 at 19:21
  • Interesting example, although the original question was about `goto` from inside a `try` block, not a `catch` block. – Adam Rosenfield Jul 12 '12 at 20:55
  • @AdamRosenfield indeed. I figure I didn't make this clear enough. Lemme edit. – Johannes Schaub - litb Jul 12 '12 at 20:56
  • @AdamRosenfield, FWIW, I was googling specifically for gotoing out of a catch block, and I was very grateful for this answer covering that, too, on a page where I could, thus, get a fairly complete picture. – Sz. Aug 07 '19 at 13:40
11

Standard Says yes, it's legal & well-defined:

C++2003: 6.6 Jump Statements

On exit from a scope (however accomplished), destructors (12.4) are called for all constructed objects with automatic storage duration (3.7.2) (named objects or temporaries) that are declared in that scope, in the reverse order of their declaration. Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of variables with automatic storage duration that are in scope at the point transferred from but not at the point transferred to. (See 6.7 for transfers into blocks). [Note: However, the program can be terminated (by calling exit() or abort()(18.3), for example) without destroying class objects with automatic storage duration. ]

I choose not to comment on the religious implications of using goto in the first place.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
7

Even more specifically than the C++03 standard's section on jump statements, it says this about try-blocks in the "Exception handling" clause (15/2):

A goto, break, return, or continue statement can be used to transfer control out of a try block or handler. When this happens, each variable declared in the try block will be destroyed in the context that directly contains its declaration.

C++11 contains the same wording.

Note however, that's it's not OK to jump into a try-block using a goto (or switch):

A goto or switch statement shall not be used to transfer control into a try block or into a handler.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
1

It's legal. It's bad code. Don't do it. Don't use goto.

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • 3
    `goto` has its uses, but mixing it in with C++ exception handling is definitely not one of them. – Adam Rosenfield Jul 12 '12 at 19:08
  • 3
    As someone famous said, "All generalizations are false, including this one". See [this answer](http://programmers.stackexchange.com/a/133523/33478) for an argument that `goto` can actually be useful sometimes -- mostly to make up for a feature that's missing from the language you're using. (I'm not arguing that jumping out of a `try` block is a good idea.) – Keith Thompson Jul 12 '12 at 19:09
  • @Keith About your link: 2. is a good reason for C code but not really necessary in modern C++. 3. can make sense, although I think a simple while loop with the switch inside is just as fine (as you say yourself :) ). 1. can be handled nicer by creating an additional function. So in general I think simply agreeing that gotos are bad isn't such a bad thing in c++ because one gets by just fine without it and well we see what happens if it gets used ;) – Voo Jul 12 '12 at 19:14