13

I have seen programs using this strategy and I have also seen posts considering this bad practice. However, the posts considering this bad practice have been written in c# or some other programming language, where there are some error handling built in. This question is about the c++. Further, the errors I am addressing are errors which are fatal enough to force a program to shutdown, not some general "maybe-I-have-missed-something-error". With using expressions at highest level I mean this in a bit sloppy sense. It can be either something like

int main(){
    try {
        //run
    } catch (fatalException){
        //handle error and shutdown
    }
}

or it can be something like this in for example a graphical application.

void runApplication(){
    try {
        //run
    } catch (fatalException){
        //handle error and shutdown
    }
}

The alternative to this would be to handle this error where it happens and hierarchically return from functions, one-by-one until the program is terminated. The reason I can see for terminating fatal errors by a try-catch on the top level is that the reasons for this kind of error can be different, and is probably fairly unusual (corrupted databases, some out-of-memory errors, corrupted configuration files, etc...). Handling exceptions locally and return from functions one-by-one would make the code less clear and require much effort to handle problems which are unlikely to occur.

However, I am not sure whether it is good practice to start the program with a try. Personally, I think it is ugly, but somehow this ugliness reflects the ugliness of the problem itself, so this may not be a reason to not use it for this case.

EDIT I may have misunderstood the dupe post, but I do not think this solves the problem. The question is not about not-catching some exceptions. The point is that there is in most cases are other parts of the code which can handle the exception closer the the throw in a fairly satisfactory way, but to the cost of having to step through the hierarchy to the top and terminate. However, since the program would still need termination, are there in general any reason to catch earlier that on top level? One can argue that this implies that the lower levels are unable to decide how to handle this. But in this case I believe it is unclear. I mean "what error would have the authority to determine if a program needs to terminate?"

5
  • 2
    Exceptions: Why throw early? Why catch late?
    – gnat
    Commented Feb 1, 2016 at 7:33
  • @DocBrown It is not exactly what I ask about. The question is not about not-catching some exceptions. The point is that there is in most cases are other parts of the code which can handle the exception closer the the throw in a fairly satisfactory way, but to the cost of having to step through the hierarchy to the top and terminate. However, since the program would still need termination, are there in general any reason to catch earlier that on top level? One can argue that this implies that the lower levels are unable to decide how to handle this, but in this case i believe it is unclear.
    – patrik
    Commented Feb 1, 2016 at 7:45
  • Ok, when thinking about my edit it seems as I start to argue against myself. I will wait for some time and see if anyone have manage to give a proper answer to this post. In case not I can probably consider it to unclear and delete it.
    – patrik
    Commented Feb 1, 2016 at 7:54
  • If something is corrupted with unknown cause you'll have a hard time handling that anywhere.
    – usr
    Commented Feb 1, 2016 at 14:26
  • I strongly disagree about the duplicate vote. This question may be a duplicate of something, but not that question.
    – user22815
    Commented Feb 1, 2016 at 15:49

2 Answers 2

21

I have a question regarding the use of exceptions at the highest level of a program.

I have seen programs using this strategy and I have also seen posts considering this bad practice.

However, the posts considering this bad practice have been written in c# or some other programming language, where there are some error handling built in.

This question is about the c++.

The principles of [Structured] Exception Handling are largely language independent.

Any Unhandled Exception will kill your program. What you're seeing here are "backstop" Exception Handlers that do little more than record the exception somewhere (so that you can examine it later) and show the user a big, friendly "Oops" message, instead of the nasty, system-generated one.

The alternative to this would be to handle this error where it happens and hierarcially return from functions, one-by-one until the program is terminated.

That'a a terrible idea.

Use the Right Tool for the Right Job.

  • Flow Control - regular call and return.
  • Exceptional stuff that causes havoc - Exceptions.

You've got the idea of why to throw Exceptions but I think you're missing the [far] more important part that is where and why to catch (or "handle") them.

OK, so you're database is corrupted.
Do you just crash the program?
Or do you let the user, say, open a backup copy of the database?
Or open the program is some "diagnostic" mode to try and sort the problem out.

These are actions that your program can perform - ways to "handle" your CorruptDatabaseException, say, if and when it happens.

Yes, Exceptions are .. exceptional.

You don't expect them to happen in normal operation but, by creating an Exception for such a case, at least you've thought about the possibility of it happening and put some "response" in place to deal with it. It might well be that that action is just "shut the program down (and tell the user why)". In some cases that's all you can do and, for that, the Backstop exception catcher will probably do.

The point is that there is in most cases are other parts of the code which can handle the exception closer the the throw in a fairly satisfactory way, but to the cost of having to step through the hierarchy to the top and terminate.

Again, a crucial part of Exception Handling is that, having successfully handled an Exception, the rest of the program must be able to continue as though the Exception had never happened. If your program can't do that, then the Exception is still happening, in which case you need to re-throw it up the call chain until something can handle it (even if, eventually, that's just to kill the program).
This is the principle behind the "finally" block seen in C#; "clean-up" code in any try-catch block that gets automatically executed as an Exception "passes through" it, on its way up through the call stack, on its way to being handled.

However, since the program would still need termination, are there in general any reason to catch earlier that on top level?

If you were to code something like ...

throw new KillProgramException(); 

... then no. The intention is pretty clear and you wouldn't expect anything in your program to try and handle this (except, perhaps, the "backstop").

I mean what error would have the authority to determine if a program needs to terminate?

Depending on circumstance, it might be absolutely any of them!

In some uber-critical section of code, an IndexOutOfRangeException might be just a fatal as DatabaseCorruptException.

5
  • Great! This was exactly what I was wondering about. Thank you for the answer. With In some uber-critical section of code, an IndexOutOfRangeException might be just a fatal as DatabaseCorruptException. I assume that I should catch the first exception (which may be thrown by a library or DB or so) and rethtrow a KillProgramException. Is that what you meant? Anyway I will accept this. Thanks again.
    – patrik
    Commented Feb 1, 2016 at 13:17
  • 3
    @patrik: IMHO you got it only half. Your comment sounds you are still seeking for a "one size fits all" solution, where there is none. Though what you wrote might be the correct way to handle termination *in some cases, in others it won't be. You will have to think about each individual case: which exception is appropriate, where can it be handled, does it really need to force a termination, and so on. ...
    – Doc Brown
    Commented Feb 1, 2016 at 13:43
  • 2
    @patrik: ... What to do heavily depends on the context. If you are writing a reusable lib, throwing a KillProgramException might be never a good idea. In an application which uses such a lib, mapping exception XYZ to a KillProgramException by a rethrow might be the best solution you can provide. So don't look for a general "no-brainer" here.
    – Doc Brown
    Commented Feb 1, 2016 at 13:50
  • @DocBrown I should probably not write this, but have a dislike for unresponded comments. They seem to indicate that I do not care about your time and effort. So your comments are noted and I agree, good point. And yes, I do not think termination is a good way for a library to handle errors. Anyway thanks for bothering about idiots like me :).
    – patrik
    Commented Feb 1, 2016 at 14:53
  • 1
    @patrik: a question which got 5 upvotes here on Programmers and really a good top answer is surely a good question, so there is no reason for you to feel like "an idiot" (and if I were thinking that way about you, I would not have spend my time for answering or commenting here ;-) ).
    – Doc Brown
    Commented Feb 1, 2016 at 15:00
6

Clearly in your main () function you don't have a chance to handle the exception in any meaningful way. If an exception reaches main (), all you know is that something went badly wrong.

You can of course decide how you want to handle the situation that "something went badly wrong". That's not at all a bad practice. You may of course decide that you handle this by doing nothing (which means your program will crash). You may decide to handle this by telling the user that something went wrong, and then exit. Which is depending on the environment either better or worse than just crashing (in an iOS application, it would be considered worse). You may decide to handle this by saving what can be saved and then exiting; this is something that must be done very carefully because you know that something just went badly wrong. Or you may decide to keep your app running, which also must be done very carefully because you know that something just went badly wrong.

Summary: It's not a bad practice. It should be a conscious decision, and catching the error at this level should add something of value. A catch a this point that doesn't do anything is obviously useless, but doesn't do any damage either. So it might make me wonder "why is the developer doing that", but it doesn't hurt.

Should you handle it earlier: If an exception is something that you know how to handle, then obviously handle it. If you know that an exception can just be ignored, ignore it. If you don't know how to handle it, and don't know that it can be ignored, either figure out how to handle it, or figure out that you can ignore it, or do not catch it because such an exception means "something went badly wrong". And if you actually know that you can't handle an exception because it just means "something went badly wrong" then don't catch it either.

Not the answer you're looking for? Browse other questions tagged or ask your own question.