abstraction level of error handling

N

nguyenminhhai

Hi everyone, I'm reading "The C++ Programming Language" (Bjarne
Stroustrup, 3rd edition). At page 193, he said "Doing error handling
using the same level of abstraction as the code that caused the error
is hazardous; the error-handling code might repeat the same error that
triggered the error handling in the first place", and I don't
understand it clearly. So it would be very nice if someone here can
explain it more clearly. Thanks in advance.
 
R

Rolf Magnus

nguyenminhhai said:
Hi everyone, I'm reading "The C++ Programming Language" (Bjarne
Stroustrup, 3rd edition). At page 193, he said "Doing error handling
using the same level of abstraction as the code that caused the error
is hazardous; the error-handling code might repeat the same error that
triggered the error handling in the first place", and I don't
understand it clearly. So it would be very nice if someone here can
explain it more clearly. Thanks in advance.

An example of what I think he means: If you have a memory allocation error,
and you return an error message or throw an exception that contains the
message as type std::string, you might trigger the same error again,
because std::string needs to allocate memory.
 
T

tony_in_da_uk

Hi everyone, I'm reading "The C++ Programming Language" (Bjarne
Stroustrup, 3rd edition). At page 193, he said "Doing error handling
using the same level of abstraction as the code that caused the error
is hazardous; the error-handling code might repeat the same error that
triggered the error handling in the first place", and I don't
understand it clearly. So it would be very nice if someone here can
explain it more clearly. Thanks in advance.

Rolf gave a good example.

Also, say you heave two headers error.h and streaming.h. If a
function in streaming.h finds the active precision value is negative,
it might call a function in error.h, but - even if only years later
during "improvements" to error.h, it might use the whiz-bang features
in streaming.h to pretty-print the error information. And so,
potentially, round and round she goes. In this scenario, the routines
exist at the same level of abstraction, and both are calling each
other, hence the possibility of a cycle.

As a reaction to this potential, and most beneficial in projects too
large/loose to coordinate well and/or with volatile code, developers
can consider the big picture aspects of "this library is above or
below that one", and agree that the dependency will be one-way.
Though on a much bigger scale, it's similar to having a single-
translation-unit program where you don't let yourself declare
something before defining it, as you're ensuring an ever-upward flow
of dependency culminating in main().

Anyway, this approach prevents cyclic issues, but if used followed
blindly, can also make it frustrating to access needed functionality
if you find the design didn't cater for your use. Large scale
refactoring every times this happens may not be a realistic option.
But at least for low-level error handling in less managed but volatile
code, this simple separation of levels of abstractions is a sound
approach. In an academic sense, it can also be considered to be
necessary for thorough independent testing of components.

So, in the example above, the cyclic dependency can be broken by
either adding error__private_streaming.h/cc good enough to support
error.h while promising not to call back into error.h, or creating a
cut-down streaming__private_error.h/cc to support streaming.h without
using error.h. This corresponds to the choice of which to put higher
in the levels of abstraction.

Tony
 

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

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,271
Latest member
BuyAtenaLabsCBD

Latest Threads

Top