Christian said:
Hi,
assert and error handling can be used for similar purposes.
When should one use assert instead of try/catch and in which
cases the error handling is preferable?
I've read somewhere that assert could be used to start
an interactive debugger automatically. How do I realize that
on a Linux machine using gcc?
Thank you
Chris
Some programmers do think that assertions and error handling are
roughly synonymous. But they could hardly be more mistaken. Asserted
conditions and error handling are in fact two unrelated programming
practices that should always be carefully distinguished from one
another. Much of the difficulty in communicating the distinction, I
believe, derives from the fact that the word "error" figures
prominently in the descriptions of each of them. But the types of
errors referred to in either case, are completely different.
Assert expressions are used to find programming errors: either errors
in the program's logic itself or in errors in its corresponding
implementation. An assert condition verifies that the program remains
in a defined state. A "defined state" is basically one that agrees with
the program's assumptions. Note that a "defined state" for a program
need not be an "ideal state" or even "a usual state", or even a "useful
state" but more on that important point later.
To understand how assertions fit into a program, consider a routine in
a C++ program that is about to dereference a pointer. Now should the
routine test whether the pointer is NULL before the dereferencing, or
should it assert that the pointer is not NULL and then go ahead and
dereference it regardless?
I imagine that most developers would want to do both, add the assert,
but also check the pointer for a NULL value, in order not to crash
should the asserted condition fail. On the surface, performing both the
test and the check may seem the wisest decision. But such a decision
shows that information is actually lacking. The programmer does not
know whether a NULL pointer in this situation means that the program is
in undefined state or not. But the program is in one state or the
other. If the pointer is not NULL in every one of the program's defined
states than the assert's NULL check is sufficient. Whatever the program
does afterwards is not covered by the program's design. The best that
can happen is the the program crashes right away. On the other hand, if
the pointer being NULL does not place the application in an undefined
state, then not to check it for a NULL value would be a programming
error before dereferencing it. By the same token, the program's remains
in a defined state regardless of a NULL-valued pointer, so an assert on
the pointer's value would not an assertable condition.
Unlike its asserted conditions, a program's error handling refers not
to errors in the program, but to inputs the program obtains from its
environment. These are often "errors" on someone's part, such as a user
attempting to login to an account without typing in a password. And
even though the error may prevent a successful completion of program's
task, there is no program failure. The program fails to login the user
without a password due to an external error - an error on the user's
part. If the circumstances were different, and the user typed in the
correct password and the program failed to recognize it; then although
the outcome would still be the same, the failure would now belong to
the program.
The purpose of error handling is two fold. The first is to communicate
to the user (or some other client) that an error in program's input has
been detected and what it means. The second aim is to restore the
application after the error is detected, to a well-defined state. Note
that the program itself is not in error in this situation. Granted, the
program may be in a non-ideal state, or even a state in which can do
nothing useful, but there is no programming errorl. On the contrary,
since the error recovery state is one anticipated by the program's
design, it iss one that the program can handle.
To communicate runtime errors, developers will often use asserted
conditions. Unfortunately, this practice further blurs the distinction
between the program's defined and undefined states and between external
and internal errors. For example, testing whether a network server is
reachable is probably not a reasonable asserted condition for a network
application. Unless it is OK to expect the program to crash whenever a
server becomes unreachable, the program should be able to handle this
situation. On the other hand, it is important to convey to a tester
that the reason that the network server cannot be reached is due to an
external condition, and not due to a programming error.
To report external error conditions, I would recommend adopting an
assert-like mechanism, but one that carefully distinguishes these type
of reports from true assertion failures - which are, and should always
be, the detection of a programming error. The rule of thumb should be:
if a program does not crash after an assertion failure then the bug is
either a bogus asserted condition, or a failure in the program's logic
that prevents the program from crashing when it should.
Greg