Boost logo

Boost :

From: David Bergman (davidb_at_[hidden])
Date: 2002-11-20 20:20:51


I do not know if I would necessary like to have such a hard coupling
between exceptions and logging/tracing...

First of all, the exception-carrying objects get kind of heavy.
Secondly; I think it is good to regard exceptions as something a bit
more than carriers of either (1) log information or (2) a last message
before aborting (which is sometimes implicit in arguments around
exceptions...). I am not saying that your brief sketch of your
home-brewed exception handling indicates that you do not appreciate the
non-logging facet of exceptions, just want the overall discussion of
exceptions not to diverge into pure logging issues.

Thanks,

David

-----Original Message-----
From: boost-bounces_at_[hidden]
[mailto:boost-bounces_at_[hidden]] On Behalf Of
scleary_at_[hidden]
Sent: Wednesday, November 20, 2002 4:03 PM
To: boost_at_[hidden]
Subject: RE: [boost] Do we need a boost_exception class or idiom?

> Has anyone run into a comprehensive attack on these and similar
exception
> class problems? Is there a better way than each Boost developer just
> hacking together individual exception classes? Could we do better with
a
> Boost exception class or idiom?

I can only speak from my own personal experience, here...

In my own code, a base class has evolved over time, which I call simply
'error' (in my own namespace, of course). It has the following
properies:
. Publicly derives from std::exception.
. Contains a std::string member containing the exception message (msg_).
msg_.c_str() is returned to satisfy std::exception::what(). A constant
reference to msg_ is returned from a member function message(); this is
provided as a convenience.
. Contains another std::string member containing an xml description of
the
exception. A constant reference to this member is returned from the
member
function xml().
. The constructor is declared protected, and has the following
signature:
  error(const string & type, const string & message,
        const string & funcname = string(), const string & code =
string())

Furthermore, I have evolved the following practices:
. The "exception message" is always of the form:
  [ErrorTypeName] error `[ErrorMessage]'
with an optional postfix:
  from `[FunctionName]'
. The "xml description" is of the form:
  <error type=[ErrorTypeName] message=[ErrorMessage]
function=[FunctionName]
code=[ErrorCode]/>
Though this is a loose definition; 'function' and 'code' are optional,
'error's may be nested arbitrarily, and additional attributes may be
added.
It is always guaranteed to be valid XML, however.
. The "[FunctionName]" is intended to be the name of the OS/library
function
that returned an error; but whenever possible additional runtime
information
should be included in parenthesis after the actual function name, e.g.,
"CreateFile ([AttemptedFileName])" or "WriteFile (async callback)".
. The "[ErrorMessage]" is a string error taken from an OS/library lookup
function, specific to a derived error class. It should be trimmed
(i.e., no
trailing whitespace), but may contain whitespace (including newlines).
If
the error code is not known by the lookup function, either "Unknown
error
[ErrorCodeDec]" or "Unknown error 0x[ErrorCodeHex]" should be used.
. There is a one-to-one mapping between derived error classes and values
of
"[ErrorTypeName]".

The constructor for error() enforces the first two of the practices that
have evolved.

However, as I said in the beginning, this has evolved fully from my
personal
experience:
. I regularly have to store errors on disk or send them to other
programs,
and I find the xml member useful for this.
. These are designed for a hierarchy of error classes, each one
responsible
for a separate API. For example, here's a partial listing:
  error
    Win32_error
    COM_error
      OLE_error
        OLEDB_error
      DirectX_error
    socket_error
. The need for nested errors and extendable error attributes (i.e., most
of
the complexity) came from my OLEDB_error derived class.
. In general, I want to capture as much information as reasonably
possible.

Conventions have also evolved for the design of derived classes, but I
don't
see any need to post those at this time.

For a Boost error base class or idiom, I would suggest at least the
following:
. A strict definition of the exception message
. Public derivation from std::exception for all exception classes
. Contains a member of type std::string for the exception message. It
took
a while for this to evolve in my 'error' (due to performance and
resource
allocation concerns), but I am convinced this is the way to go.

Moving beyond that is more tenatious ground; one of the main questions
on my
mind is should an exception hierarchy be structured after API interfaces
(like mine), or after Boost libraries? I just don't want to see a lot
of
rework where each Boost library would have their own Win32_error class
or
format_message function. OTOH, structuring an exception hierarchy after
API
interfaces makes perfect sense for an end-user executable program (like
what
I write), but maybe not as much sense for a library?

Regardless of what exactly we end up with, I am in favor both of
exception
message guidelines, and of a common Boost error base class providing
reasonable functionality.

        -Steve
_______________________________________________
Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk