What you seem to be caught in is the specific hell of someone trying to have their cake and eat it too.
RAII and exceptions are designed to go hand in hand. RAII is the means by which you do not have to write a lot of catch(...)
statements to do cleanup. It will happen automatically, as a matter of course. And exceptions are the only way to work with RAII objects, because constructors can only succeed or throw (or put the object in an error state, but who wants that?).
A catch
statement can do one of two things: handle an error or exceptional circumstance, or do cleanup work. Sometimes it does both, but every catch
statement exists to do at least one of these.
catch(...)
is incapable of doing proper exception handling. You don't know what the exception is; you can't get information about the exception. You have absolutely no information other than the fact that an exception was thrown by something within a certain code block. The only legitimate thing you can do in such a block is to do cleanup. And that means re-throwing the exception at the end of the cleanup.
What RAII gives you with regard to exception handling is free cleanup. If everything is RAII encapsulated properly, then everything will be properly cleaned up. You no longer need to have catch
statements do cleanup. In which case, there is no reason to write a catch(...)
statement.
So I would agree that catch(...)
is mostly evil... provisionally.
That provision being proper use of RAII. Because without it, you need to be able to do certain cleanup. There's no getting around it; you have to be able to do cleanup work. You need to be able to ensure that throwing an exception will leave the code in a reasonable state. And catch(...)
is a vital tool in doing so.
You cannot have one without the other. You cannot say that both RAII and catch(...)
are bad. You need at least one of these; otherwise, you're not exception safe.
Of course, there's one valid-though-rare use of catch(...)
that not even RAII can banish: getting an exception_ptr
to forward to someone else. Typically through a promise/future
or similar interface.
My coworkers says that you should always know what exceptions are to be thrown and that you can always use constructs like:
Your coworker is an idiot (or just terribly ignorant). This should be immediately obvious due to how much copy-and-paste code he's suggesting that you write. The cleanup for each of those catch statements will be exactly the same. That's a maintenance nightmare, not to mention readability.
In short: this is the problem that RAII was created to solve (not that it doesn't solve other problems).
What confuses me about this notion is that it's generally backwards to how most people argue that RAII is bad. Generally, the argument goes "RAII is bad because you have to use exceptions to signal constructor failure. But you can't throw exceptions, because it's not safe and you'll have to have lots of catch
statements to clean everything up." Which is a broken argument because RAII solves the problem that the lack of RAII creates.
More than likely, he's against RAII because it hides details. Destructor calls aren't immediately visible on automatic variables. So you get code that gets called implicitly. Some programmers really hate that. Apparently, to the point where they think having 3 catch
statements, all of which do the same thing with copy-and-paste code is a better idea.
...
" while my question focus on "Should I better catch...
or<specific exception>
before rethrowing"main
,catch(...) { return EXIT_FAILURE; }
might well be right in code that isn't running under a debugger. If you don't catch, then the stack might not be unwound. It's only when your debugger detects uncaught exceptions that you want them to leavemain
.