[cairo] cairomm exception handling questions

Larry Lewis lewislp at yahoo.com
Mon Aug 11 15:32:56 PDT 2008


----- Original Message ----

> From: Ian Britten <britten at caris.com>
> To: cairo <cairo at cairographics.org>
> Sent: Monday, August 11, 2008 2:45:35 PM
> Subject: Re: [cairo] cairomm exception handling questions
> 
> Murray Cumming wrote:
> 
> >>    Wouldn't it make it more consistent to throw all cairomm
> >>    exceptions as Cairo::logic_error?  Currently, I (as a programmer
> >>    trying to trap all Cairo exceptions and downgrading them to
> >>    errors) must add multiple 'catch' statements to all my 'try'
> >>    statements.  That seems like it'll get repetitive/tedious pretty
> >>    quickly..  :(
> > 

Although it may be tempting, rethrowing all inner exceptions with a
common exception class will force users to look at an error code in the
exception (if present), or worse, parse the what() message to react to
different causes. I'd instead recommend annotating your class API with
all exceptions that can be thrown, whether directly or indirectly, so
that there's no surprises. The end user can always catch(...) if they just don't care.

> > Of course you shouldn't be catching the exceptions for every call.
> > That's why they are exceptions.
> 
> Admittedly, my experience with exceptions is fairly limited.
> However, as a library writer trying to add a Cairo 'canvas' to
> our existing framework, I would think that I would want to catch
> the exceptions, wouldn't I?  The higher-level code is certainly
> NOT exception-safe, and I'm trying to ensure no exceptions(*)
> propagate out.  [ Thoughts/Suggestions/Guidelines welcome ]
> 
> (*) Admittedly, exceptions like 'new' are a bit different, but I'm
> mostly interested in the cairo-specific errors/problems that I
> can fix/prevent/handle/etc.
> 

Exceptions need to propagate out when you can't suppress the exception and still maintain the class invariant. In the example mentioned, a call to Pdf::create() that fails must throw an exception since the surface is left in a unusable/unknown state (or so I assume). As a user of a library, it's *extremely* easy to ignore error return values but requires work to ignore an exception.

My rule of thumb is to always use an exception whenever an error should not occur under normal operating conditions. In other words, a successful test of all of a program's functionality should never hit a single catch block. The use of bool or error return values to indicate the success of an operation should be limited to special try* functions that for performance reasons need to avoid the overhead of an exception.

Of course, I know several people who never use exceptions (mostly old C programmers) and manage to write clean, consistent C++ code, so it's really a matter of preference and style.

Larry



More information about the cairo mailing list