General exception Handling question

J

jack

Hi,

Just a question on exception handling and the stack trace...

Throughout my application when any data access is ocurring, i use a
try-catch for exception handling to simply display an error message. This is
good and working well. I now notice that this exact same general error
message is littered through-out my program. So I decided to remove all the
try-catch blocks and catch the error at a higher level. This is good
practice in terms of structured exception handling as far as I know.

But this requires me to have most of my code in a single try block (in order
to catch any exception )e.g.

// Very start of prog
try
{
ExecuteMyProg();
}
catch( SqlException ex )
{
MessageBox.Show( "ERROR! " + ex.Message );
}

Is this good practice? Doesn't it 'slow down' the application if you
expanding the try block over a wide area of the code (instead of before
where there were many smaller try blocks) ?

Jack.
 
S

Stephany Young

Do you have any timing data that makes you think it would 'slow it down'.

I think you will find a myriad of opinions on the subject but in my opinion,
if there were any performance hit then it would be infestisimal. I'ts really
a matter of personal style.
 
P

Peter Duniho

Hi,

Just a question on exception handling and the stack trace...

Throughout my application when any data access is ocurring, i use a
try-catch for exception handling to simply display an error message.
This is
good and working well. I now notice that this exact same general error
message is littered through-out my program. So I decided to remove all
the
try-catch blocks and catch the error at a higher level. This is good
practice in terms of structured exception handling as far as I know.

I think this is apples and oranges.

Good exception handling is to catch exceptions that you either can recover
from, or that you need to handle and rethrow (in order to clean something
up, other than what can be done automatically with a "using" statement).

Good error reporting is to have a standardized, centralized way of
reporting errors that can be called from multiple places. For example,
defining a string constant or some kind of numeric ID that can be used to
look up error strings. For applications that will be localized, I believe
that there's even good support within .NET for dealing with strings in an
easily-localized way; unfortunately, I don't have the details on that, not
having had to use it myself.

The two do relate a little, in that providing the user with more specific
information is often useful, and sometimes you need to catch an exception
at a lower level in order to provide that information. But other than
that, they aren't really the same question.

Looking at your question, which pertains to where to handle an exception,
the answer is found in the former description. Yet, your motivation for
the change seems more related to the latter. That is, the issue of having
"this exact same general error message...littered throughout my program"
isn't really relevant to where you handle the exception, though it could
argue in favor of using some sort of consistent, constant-based error
reporting.
[...]
Is this good practice? Doesn't it 'slow down' the application if you
expanding the try block over a wide area of the code (instead of before
where there were many smaller try blocks) ?

If anything, I would expect having multiple try/catch blocks to be slower,
because it takes time to store the state required in order to return to a
specific try/catch block. Entering and leaving try/catch blocks over and
over is going to take more time than entering a single try/catch block and
then just running the rest of the code.

Now, is at the top level of your call chain the right place to put a
try/catch block? Well...what could you do about it if you caught the
exception at a lower level? Can you provide the user with more specific
information that would help them prevent the error? If so, then catching
the exception there might be useful. You wouldn't necessarily need to
report the error at that point; you could use that information somehow to
provide additional details when the error is finally reported higher up.

But in this case, it sounds like you are always reporting the same thing
to the user. So, assuming there's not anything you can actually do about
the error at the lower level, I think that it's fine to handle the
exception higher up, reducing the number of try/catch blocks you need to
write in the process.

Pete
 
F

Fredo

I agree with Peter. It's best to do the exception handling as close to the
exception as possible. The idea is to catch the exception and, if possible,
recover from it cleanly. If you can't recover from it, then you should
rethrow it or throw another exception that gets handled higher up or crashes
the app.

The goal of exception handling isn't just reporting that there was an error.
There are many times where you should expect exceptions and be able to
handle them cleanly. For example, if you're trying to download a web page
with HttpWebRequest/HttpWebResponse and the connection times out. You're
notified by an exception and at this point, you can choose to either inform
the user or you might want to try to re-issue the request.

As for logging, again, Peter is correct. Having a central logging system is
much better. Log4net is a great tool for logging. As for localization of
error messages, that's all very easy, if you need it. You simply place all
your message strings in a .resx file and localize it as you would any other
resx file.

The idea of having a global exception handler isn't necessarily a bad thing,
but it should be able to distinguish between fatal exceptions and
recoverable exceptions, and handle them appropriately. If you simply log and
eat the exception and continue on, it's very possible to end up in an
invalid state where your application will no longer function properly.


Peter Duniho said:
Hi,

Just a question on exception handling and the stack trace...

Throughout my application when any data access is ocurring, i use a
try-catch for exception handling to simply display an error message.
This is
good and working well. I now notice that this exact same general error
message is littered through-out my program. So I decided to remove all
the
try-catch blocks and catch the error at a higher level. This is good
practice in terms of structured exception handling as far as I know.

I think this is apples and oranges.

Good exception handling is to catch exceptions that you either can recover
from, or that you need to handle and rethrow (in order to clean something
up, other than what can be done automatically with a "using" statement).

Good error reporting is to have a standardized, centralized way of
reporting errors that can be called from multiple places. For example,
defining a string constant or some kind of numeric ID that can be used to
look up error strings. For applications that will be localized, I believe
that there's even good support within .NET for dealing with strings in an
easily-localized way; unfortunately, I don't have the details on that, not
having had to use it myself.

The two do relate a little, in that providing the user with more specific
information is often useful, and sometimes you need to catch an exception
at a lower level in order to provide that information. But other than
that, they aren't really the same question.

Looking at your question, which pertains to where to handle an exception,
the answer is found in the former description. Yet, your motivation for
the change seems more related to the latter. That is, the issue of having
"this exact same general error message...littered throughout my program"
isn't really relevant to where you handle the exception, though it could
argue in favor of using some sort of consistent, constant-based error
reporting.
[...]
Is this good practice? Doesn't it 'slow down' the application if you
expanding the try block over a wide area of the code (instead of before
where there were many smaller try blocks) ?

If anything, I would expect having multiple try/catch blocks to be slower,
because it takes time to store the state required in order to return to a
specific try/catch block. Entering and leaving try/catch blocks over and
over is going to take more time than entering a single try/catch block and
then just running the rest of the code.

Now, is at the top level of your call chain the right place to put a
try/catch block? Well...what could you do about it if you caught the
exception at a lower level? Can you provide the user with more specific
information that would help them prevent the error? If so, then catching
the exception there might be useful. You wouldn't necessarily need to
report the error at that point; you could use that information somehow to
provide additional details when the error is finally reported higher up.

But in this case, it sounds like you are always reporting the same thing
to the user. So, assuming there's not anything you can actually do about
the error at the lower level, I think that it's fine to handle the
exception higher up, reducing the number of try/catch blocks you need to
write in the process.

Pete
 
D

Dejan Stanic

Not knowing the details, I cannot tell if this is 'good' or 'bad' practice,
but it surely doesn't slow your application down. As a rule of thumb,
try-ies (eh?) are dirt cheap, but catch-es can be expensive (at least for
the first time...).

LP,
Dejan
 
B

Bill Butler

Fredo said:
I agree with Peter. It's best to do the exception handling as close to
the exception as possible. The idea is to catch the exception and, if
possible, recover from it cleanly. If you can't recover from it, then
you should rethrow it or throw another exception that gets handled
higher up or crashes the app.

I was right with you until the last 4 words.
I think you should always implement a try-catch at the highest level so
that you don't "crash".
Your app will still terminate, but it will not "crash".
It will shut down in a controlled manner.

Perhaps this is what you meant by "crash".
The goal of exception handling isn't just reporting that there was an
error. There are many times where you should expect exceptions and be
able to handle them cleanly. For example, if you're trying to download
a web page with HttpWebRequest/HttpWebResponse and the connection
times out. You're notified by an exception and at this point, you can
choose to either inform the user or you might want to try to re-issue
the request.

Correct.
Handle the Exception as soon as it makes sense...and no sooner.
If you can't handle it at a given level...don't catch it.

The idea of having a global exception handler isn't necessarily a bad
thing, but it should be able to distinguish between fatal exceptions
and recoverable exceptions, and handle them appropriately. If you
simply log and eat the exception and continue on, it's very possible
to end up in an invalid state where your application will no longer
function properly.

I use the Global handler for terminal exceptions and Unknown exceptions.
Any Exceptions that can resonably be recovered from should be caught at
the point that makes the most sense as far as a clean program flow.

Bill
 
P

Peter Duniho

I was right with you until the last 4 words.
I think you should always implement a try-catch at the highest level so
that you don't "crash".

Why?

I would agree that if you have some graceful way to recover at that point,
it makes sense to handle the exception at the highest level. But that
clearly already is covered under the "recover from it cleanly" scenario.

In most cases, if you have an exception get that far up the call stack,
it's because you didn't anticipate it and have no idea how to recover.
You can't just ignore it, because you have no way to know where in the
execution of the application it happened and thus no way to know the state
of the data or how to safely put the data back into a known-good state.

The best you can do at the highest level of the application is to make the
crash look "pretty". You can display a dialog box (maybe an apology :) ),
and you might even be able to internally restart the entire application
from scratch (throw everything out, start all over). But you can't really
avoid crashing at that point. There's no way to "shut down in a
controlled manner" at that point. The best you can do is throw up your
hands, give up, and exit.

I worked on some children's software a while ago, and in that situation we
felt that we definitely should apologize if there was some sort of
crashing bug, rather than expose the kids to the relatively technical and
ugly "unexpected application exception" dialog from Windows. But in that
case, we had a full-screen, completely non-Windows UI. I'd say for more
mainstream applications, the normal Windows exception dialog is just as
good as whatever else most people would be likely to display to the user,
if anything (and I definitely hate applications that just disappear...I'd
much rather see the Windows exception than to have an application catch an
exception and then just quit on me).

In some cases an application can be structured so that you can do "safe"
operations on the data, saving the current state and then having a way to
restore that state if some unexpected error occurs. But a) this isn't
ever going to happen at the highest level of the application (there will
always be a level higher than the level at which distinct operations are
invoked, where overall control of the operations is done), and b) many
applications have no practical way to manage the operations in this way.

I'm definitely not a big fan of crashing. With very few exceptions, I
would be willing to say that any time an application crashes for any
reason, that's a bug. But the solution to that is to find and fix all the
crashing bugs. There's usually not a safe way to deliver an application
that is actually immune to crashing, and certainly putting a try/catch
block at the very top of the program to catch all exceptions isn't going
to be able to make an application immune to crashing or even allow you to
safely terminate the application.

Pete
 
A

Amar

Hi,

Just a question on exception handling and the stack trace...

Throughout my application when any data access is ocurring, i use a
try-catch for exception handling to simply display an error message. This is
good and working well. I now notice that this exact same general error
message is littered through-out my program. So I decided to remove all the
try-catch blocks and catch the error at a higher level. This is good
practice in terms of structured exception handling as far as I know.

But this requires me to have most of my code in a single try block (in order
to catch any exception )e.g.

// Very start of prog
try
{
ExecuteMyProg();}

catch( SqlException ex )
{
MessageBox.Show( "ERROR! " + ex.Message );

}

Is this good practice? Doesn't it 'slow down' the application if you
expanding the try block over a wide area of the code (instead of before
where there were many smaller try blocks) ?

Jack.

OR alternatively you caould subscribe to the
'AppDomain.CurrentDomain.UnhandledException' event of the appdomain
and write your error logging code there..
Even if you write specific try catches Iwould recommend subscribing to
this event to catch any exception not foreseen by you...
 
B

Bill Butler

Peter Duniho said:
Why?

I would agree that if you have some graceful way to recover at that
point, it makes sense to handle the exception at the highest level.
But that clearly already is covered under the "recover from it
cleanly" scenario.
Yup

In most cases, if you have an exception get that far up the call
stack, it's because you didn't anticipate it and have no idea how to
recover. You can't just ignore it, because you have no way to know
where in the execution of the application it happened and thus no way
to know the state of the data or how to safely put the data back into
a known-good state.

The best you can do at the highest level of the application is to make
the crash look "pretty". You can display a dialog box (maybe an
apology :) ), and you might even be able to internally restart the
entire application from scratch (throw everything out, start all
over). But you can't really avoid crashing at that point. There's
no way to "shut down in a controlled manner" at that point. The best
you can do is throw up your hands, give up, and exit.

Absolutely, If you reach this point you are dead anyway.
I was think more along the lines of gather what information you can for
a post mortem.
If you don't catch the exception you might get a stack trace if you are
lucky.

I guess it all depends on where your software runs.
Mine all runs in a production environment where I will get woken in the
middle of the night if my app dies a horrible death. If I am going to
get woken anyway I would prefer to have as much information as possible
at my disposal.
If I catch the exception I at least have a chance of getting all of the
information that I need written out to a log.
If I let it fly and let the app crash, I am at the mercy of OP to gather
all of the data I need.

Perhaps, if I get enough data I can fix it and avoid being woken up next
weekend.

<snip many fine points>

I rarely work on GUI based apps, perhaps I would feel differently in
that situation.

I also use the highest level handler as a way of imparting information
to the person starting my app in case there is a problem that can be
rectified (Missing files, bad config data,..) In a GUI based App you
would tend to ask for user input in the form of a dialog at that point,
in a console app it is generally easier to terminate with info as to
what is wrong, so they can fix it and try again.
When I identify one of these situations, I throw a specific exception
with enough info to fix the problem. I catch that exception in the
global handle, impart the info and terminate.

Anyway,
Perhaps our difference in opinion is nothing more that a difference in
problem domains.

Bill
 
P

Peter Duniho

[...]
Perhaps our difference in opinion is nothing more that a difference in
problem domains.

It seems likely. :) And ditto as they relate to Fredo's comments as
well. I agree that if you have a likelihood of recovering the information
from a crash, it's useful to gather it. I think that most applications
don't fit into that scenario, being delivered to a broader user base
without much, if any, direct feedback from the users.

That said, if anything I'd say that .NET applications are more likely, at
least for the time being, to be targeted at a smaller audience, so maybe
the idea of collecting data for a post-mortem makes more sense for .NET
apps than it even would generally.

Anyway, I think we all agree that it doesn't make any sense to catch an
exception you can't do anything about. :) Conversely, if there's
something you can do, even if it's just saving some information for future
reference, then it's worth catching the exception.

Pete
 
B

BlackWasp

I agree with most of the points discussed so far but would add one point
specifically for GUI applications. If the GUI holds important information
for the user that may not have been saved, it is a good idea to let the
application remain active even if it is ust to let the user do the
last-ditch action of copying the data to the clipboard. I have had users in
the situation too often where they can see the data that they desperately
require but only behing the dialog box that is telling them that the
application is going to close.

I remember this with many shrick-wrapped packages in Windows 3.1. The "The
application has failed and should be closed." type errors gave you that
get-out clause.

....or alternatively, make sure that your application saves data as it goes
and is able to recover on re-loading, in a similar manner to Microsoft Word.

--

BlackWasp
www.blackwasp.co.uk


Peter Duniho said:
[...]
Perhaps our difference in opinion is nothing more that a difference in
problem domains.

It seems likely. :) And ditto as they relate to Fredo's comments as
well. I agree that if you have a likelihood of recovering the information
from a crash, it's useful to gather it. I think that most applications
don't fit into that scenario, being delivered to a broader user base
without much, if any, direct feedback from the users.

That said, if anything I'd say that .NET applications are more likely, at
least for the time being, to be targeted at a smaller audience, so maybe
the idea of collecting data for a post-mortem makes more sense for .NET
apps than it even would generally.

Anyway, I think we all agree that it doesn't make any sense to catch an
exception you can't do anything about. :) Conversely, if there's
something you can do, even if it's just saving some information for future
reference, then it's worth catching the exception.

Pete
 
P

Peter Duniho

I agree with most of the points discussed so far but would add one point
specifically for GUI applications. If the GUI holds important
information for the user that may not have been saved, it is a good idea
to let the application remain active even if it is ust to let the user
do the last-ditch action of copying the data to the clipboard.

Frankly, while I see the value in the idea behind that goal, it's not a
very practical, or even safe, thing to try. Or at least, to provide as a
general suggestion. If you have designed the entire UI layer of the
application with this in mind, then yes...it's theoretically possible to
provide the user with a last-ditch "copy selection" minimal UI for cases
like this. If all the application uses is built-in controls like TextBox,
it might even not require a lot of extra code.

But regardless of the amount of extra code required, it's not going to be
simple to ensure that the user can _only_ do the minimal actions required
to copy and paste data, and if you've got any sort of custom UI yourself,
not only does the work required to handle something like this go up by
quite a bit, you have no way of knowing that the exception isn't being
caused in that custom code, leading the user down a frustrating tease with
no end.

To retro-fit an existing application with this sort of behavior is to
invite all sorts of new problems in the code, not only in the handling of
the exception scenario, but also providing new avenues for failure in the
common-case, non-failure scenarios. For example, it provides a whole new
possible bug in which the user cannot do anything except copy and paste
the code, even if the program hasn't otherwise failed.
I have had users in the situation too often where they can see the data
that they desperately require but only behing the dialog box that is
telling them that the application is going to close.

I too have seen programs that do this. But as frustrating as that might
be to the users, that's not really an argument for further complicating
the program and adding a whole new layer of potential bugs. The effort
would be better spent simply ensuring that the original code is
well-designed, well-written, and well-tested so as to avoid the need for
this sort of thing in the first place.

The fact is, if this sort of thing comes up with anything even
_approaching_ regularity, no sane user is going to want to use the program
anyway. So either you've got a program with way too many bugs (and if so,
what hope do you have of correctly dealing with the exception scenario
either?), or you've got clients who value their data so highly that even a
single crash per year causes an unacceptable loss (in which case, you
should simply deliver better code, and charge the customer the additional
cost that is incurred to design, implement, and test the code better, and
which is justified by their needs).
I remember this with many shrick-wrapped packages in Windows 3.1. The
"The application has failed and should be closed." type errors gave you
that get-out clause.

I remember a lot of crashes in Windows programs. Heck, I still see too
many Windows programs that are poorly written and crash too often. But
it's very rare when I see a program that tries to allow you to actually
extract data from an application that is on its way down. In fact, I
can't think of a single mainstream application that does this.
...or alternatively, make sure that your application saves data as it
goes and is able to recover on re-loading, in a similar manner to
Microsoft Word.

Auto-save can be nice, but it would be better to not need it in the first
place and again, the question is begged, if the authors of the program
can't keep it from crashing, just how reliable can we expect auto-save to
be? The most useful scenario for auto-save is actually situations where
the application has no control (for example, the whole computer locks up
because of a driver bug, or something like that). As a feature, it's not
really a solution to potential crashes...it's more for dealing with other
things that are outside the application's control.

IMHO, one of the biggest problems with software design is complexity. If
your concern is that of dealing with program errors, the solution is
definitely _not_ to increase complexity. I just do not see global
exception handling as a serious approach to program correctness.

Pete
 
S

Scott Roberts

Auto-save can be nice, but it would be better to not need it in the first
place and again, the question is begged, if the authors of the program
can't keep it from crashing, just how reliable can we expect auto-save to
be?

Well, that depends entirely on *why* the application is crashing.
The most useful scenario for auto-save is actually situations where the
application has no control (for example, the whole computer locks up
because of a driver bug, or something like that). As a feature, it's not
really a solution to potential crashes...it's more for dealing with other
things that are outside the application's control.

If we assume that an application is well-written, then *all* crashes are due
to things outside the application's control. If we assume that an
application is not well-written, then no amount of exception handling (at
any level) is going to make it magically become well-written (outside of the
fact, of course, that exception handling is *part* of a well-written
application, but then it would fall under the former).
IMHO, one of the biggest problems with software design is complexity. If
your concern is that of dealing with program errors, the solution is
definitely _not_ to increase complexity. I just do not see global
exception handling as a serious approach to program correctness.

That depends on what you mean by "program correctness". Yes, ideally there
would be no application crashes. That is a noble goal. However, if we have
already taken extreme care to eliminate as many unhandled exceptions as
possible, there is nothing wrong with an additional global exception handler
that catches exceptions, logs the exception, and let's the user know that
the exception, while unexpected, will be investigated. You mentioned earlier
that the MS dialog is as good as an application-specific one. I disagree. As
a user, I am much more "comforted" when an application is able to detect an
unexpected exception and tell me that it has been logged and/or a
notification has been sent to the vendor. At least I have some hope that the
vendor will actually investigate it and perhaps fix it. It means that they
are smart enough to know that bugs *always* exist and are willing to work on
them. An application that just crashes indicates to me that the author
doesn't expect bugs and really has no intention of fixing them ("works on my
computer").

I suppose all that has more to do with "customer service" than "program
correctness", but one could also argue that the customer experience is
paramount.
 
P

Peter Duniho

Well, that depends entirely on *why* the application is crashing.

By definition, the exception handled globally is outside the set of
exceptions that have known causes (or at least, it should be...if not,
there are other things wrong with the code).

So while it may depend on "why", the information on which that evauluation
is dependent is unavailable. There's no way to know that the application
is crashing for reasons outside the author's control. And frankly, the
valid scenarios in which that could even happen are extremely remote.
Especially in the realm of the NT-based versions of Windows, there's very
little that can happen outside the application's control that can cause
untrappable errors, and what can happen is unlikely to leave the
application available to catch an exception globally.

If the program is crashing, it's almost certainly the author's fault.
If we assume that an application is well-written, then *all* crashes are
due to things outside the application's control.

I didn't say "crashes". I specifically excluded "crashes", in fact. That
was the point of juxtaposing "not a solution to crashes" and "more for
dealing with other things".

"Other things". Like the power going out, for example. Or a video driver
causing a blue-screen error. That sort of thing. Things that _aren't_
application crashes.
[...]
That depends on what you mean by "program correctness". Yes, ideally
there would be no application crashes. That is a noble goal. However, if
we have already taken extreme care to eliminate as many unhandled
exceptions as possible, there is nothing wrong with an additional global
exception handler that catches exceptions, logs the exception, and let's
the user know that the exception, while unexpected, will be investigated.

I never said there was. Why are you trying to imply that I did?
You mentioned earlier that the MS dialog is as good as an
application-specific one. I disagree. As a user, I am much more
"comforted" when an application is able to detect an unexpected
exception and tell me that it has been logged and/or a notification has
been sent to the vendor.

This is a matter of philosophy and you're welcome to your opinion.
Suffice to say, I disagree.
At least I have some hope that the vendor will actually investigate it
and perhaps fix it. It means that they are smart enough to know that
bugs *always* exist and are willing to work on them. An application that
just crashes indicates to me that the author doesn't expect bugs and
really has no intention of fixing them ("works on my computer").

For me, an application that crashes, whether it presents a custom UI for
bug reporting or simply allows Windows to handle it, that tells me that
the author writes software sloppily. It tells me very little about what
the author expects or of their intentions; I'm surprised you think you can
infer so much about a person from so little information. You can't.

Beyond that, my experience has been that those applications that have a
custom crash UI (and they are few and far between, frankly) are those that
crash fairly regularly. In other words, there's a strong correlation
between having a custom crash UI and having a poorly written application.
I suppose all that has more to do with "customer service" than "program
correctness", but one could also argue that the customer experience is
paramount.

Of course. That's why one should invest more effort in the design,
implementation, and testing of their code and ensure that the program
doesn't have errors that would lead to a crash. As a user, if I have to
choose between an application that doesn't crash, and one that does crash
but presents me with a nice user interface tell me that it's crashed, I'm
going to pick the former every time.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top