Re: Practical error/exception handling...
From: Rob Kennedy (me3_at_privacy.net)
Date: 01/19/05
- Next message: Rob Kennedy: "Re: CodeCentral article"
- Previous message: Raptor: "Practical error/exception handling..."
- In reply to: Raptor: "Practical error/exception handling..."
- Next in thread: Raptor: "Re: Practical error/exception handling..."
- Reply: Raptor: "Re: Practical error/exception handling..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 19 Jan 2005 00:13:32 -0600
Raptor wrote:
> OK, suppose we wish to write an application that handles errors gracefully
> and is informative to both user and developer when errors occur. (Hey, don't
> laugh, it COULD happen! Heh.)
The exceptions that I want the user to know about are also the ones I
want to know about. The user doesn't necessarily need to understand
anything about them, though, only enough that he or she can accurately
relay them back to me.
> As I understand it, this is essentially usable code for handling errors with
> some grace, except that one might call a handler instead of popping up a
> message from the procedure:
>
> procedure TformMain.Button1Click(Sender: TObject);
> begin
> Try
> // Do stuff here which requires cleanup...
> Try
> Memo1.Lines.LoadFromFile('nosuch.txt');
> Except
> On E: Exception do
> begin
> ShowMessage('Button1Click: ' + E.Message);
> end
> end;
> Finally
> // Cleaning up
> end;
> end;
I wouldn't consider it usable code for handling errors. Why? Because it
doesn't *handle* anything. In fact, it explicitly *doesn't* handle any
error. It just tells the user what the error's message was and what
method it occured in.
The only place you should ever catch *all* exceptions is at the very
base of the call stack, as a last resort to keep the program from
terminating. As it happens, Delphi already does that. If you don't catch
any exceptions in your OnClick event handlers, all Delphi will do is
catch the exception, display its message, and continue on as though
nothing had happened. (You can augment that behavior by handling the
Application.OnException event.)
Exceptions are *supposed* to escape from the routines that raise them.
They're supposed to percolate through the nests of try-finally and
try-except blocks until they reach the exception handler that really
knows how to handle the exception.
Also, given that code, the try-finally block should go inside the
try-except block. Otherwise, the try-finally block isn't really
protecting anything. By the time execution reaches the finally section,
any exception has already been "handled" and cleared, which means that
execution would have reached the code within the finally section whether
or not the try-finally block was there at all.
> A few questions:
>
> Would this sort of code be used in ALL procedures and functions of
> consequence, or just selected ones? If the latter, how does one decide where
> to place such traps?
The only time you should ever write a try-except statement is when you
have a clear idea of exactly what your program needs to do to recover
from the precise type of exception you caught. Otherwise, you should
ignore the exception and hope it gets caught further up the chain.
If you have a catch-all exception handler, then it should probably also
end with a "raise" statement to allow the exception to continue through
the stack to the next exception handler. Consider for example the
following function.
function GetNewList: TList;
begin
Result := TList.Create;
try
// [populate the list]
except
Result.Free;
raise;
end;
end;
When you write an on...do clause, you should use as specific a type of
exception as you can get. Don't catch EMathError when you're really just
looking for EZeroDivide, for instance.
Furthermore, the kind of exception handler that you illustrate above is
better accomplished by a global exception handler, like the one
installed by MadExcept or JclDebug. They insert an exception handler at
the base of the call stack, so if any exception goes unhandled, they
will interrupt with a message telling the user where the exception
occured, including the exception's address. They also provide a call
stack, so rather than simply knowing that an exception occured somewhere
in Button1Click, you'll know exactly what procedure Button1Click was
calling when the exception was raised. You'll even have the line number
and source file name. (Line numbers aren't always accurate, but they're
usually pretty close to the offending line.) These exception handlers
can even be configured to send the error report to you by e-mail.
> In practice, could using these liberally offer feedback to the software
> manufacturer as to where IN CODE problems are arising for users? If so,
> what's a good practice for messages which might help the developer without
> annoying the user?
In practice I think that kind of code structure would lead to
maintenance headaches. You need to remember to include it every time you
write a routine, and you need to make sure you update the string if you
rename a method or move it to a different class or unit.
More useful than the exception's Message property is the exception's
ClassName value and the global ExceptAddr value. They tell you what kind
of exception occured and where it occured.
> Does one place the string constants in each code location, as I've done in
> this instance, or would localization (internationalization) issues (or code
> organization) prompt one to collect it in one place for easier translation
> or management?
The stack traces generated by MadExcept and JclDebug get procedure names
by consulting the map file of your program. Control the generation of
the map file on the Linker tab of the project-options dialog. The map
file is just a text file; look at its contents yourself to get an idea
of just how detailed a detailed map file is.
-- Rob
- Next message: Rob Kennedy: "Re: CodeCentral article"
- Previous message: Raptor: "Practical error/exception handling..."
- In reply to: Raptor: "Practical error/exception handling..."
- Next in thread: Raptor: "Re: Practical error/exception handling..."
- Reply: Raptor: "Re: Practical error/exception handling..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|