Topic: exception-handling strategies (Internationalization/localization support in stdlib)


Author: rmaddox@isicns.com (Randy Maddox)
Date: Fri, 19 Jul 2002 21:07:23 GMT
Raw View
>
> Imagine we are writing a destructor of some object that must call a cleanup
> function in some DLL, whereby we are a) not completely certain that it won't
> throw an exception and we don't even know what type and b) we cannot allow
> any exceptions to propagate outside the destructor because everyone knows
> that is a Bad Thing. So in this case the typical advice has been that you
> can use a catch-all & swallow-type thing to prevent any exceptions from
> leaving the destructor, because there is no other sensible place for them to
> go anyhow. (I am pretty sure I'm not just making this up out of my own
> ignorance, I'm sure you've read similar things too.)
>
> Obj::~Obj()
> {
>    try {
>      dll_cleanup_func_that_may_do_whatever_crazy_thing();
>    }
>    catch (...) { /* swallow it, maybe log some random information, but don't
> rethrow */ }
> }
>

Why would you log "some random information"?  You at least know where
in the code the problem was detected, and you know what you did right
before the problem occurred.  Also, you might be able to use
GetLastError() in Windows, or errno in Unix/Linux, to see if the OS
can provide some useful information.  Just because you don't know the
type of the exception does not imply that you know nothing.

> Now frankly if you are using some DLL that can throw any random exception
> that is not inherited from std::exception, then you're just SOL. Because
> using catch(...) is just as, if not more, dangerous to stability here than
> allowing random exceptions to propagate, since it may pick up hardware
> exceptions too, and you do _not_ want to swallow a hardware exception (at
> least not here). If you are unable to change the DLL's behavior because it
> is some third-party code that you purchased and all you have is some binary
> code, well I guess you're just up against a wall. Try to get the vendor to
> fix it. On Windows there is apparently a workaround whereby you can prevent
> hardware exceptions from coming through the catch(...). I guess you could
> try that, but it's clearly not a portable solution. Then again maybe
> portability isn't even an issue for you. I would prefer that people would
> start making it a point to always derive their exception objects from
> std::exception and not just throw ints or char*s or whatever random
> hierarchies. Consider how much more straightforward and portable and simpler
> everything is if all the exceptions being used are derived from
> std::exception. (Can anyone point out any objections to the notion of
> inheriting all exception objects in ordinary user code from std::exception?
> Except for certain very special cases which would specifically be intended
> to go around this paradigm in the same way as we are trying to let hardware
> exceptions pass uninterrupted, all exception objects should be inherited
> from std::exception.)
>
> Obj::~Obj()
> {
>    try { ... }
>    catch (std::exception&) { /* swallow it, maybe log some info, don't
> rethrow */ }
> }
>
> The catch here ;-) is that this relies on all user exceptions being derived
> from std::exception in some way. Maybe that's too fragile for some people
> (in my case it works just fine, since for our inhouse software we control
> the entire code base, and the few-and-far-between third party packages we
> use are open-source, so we can fix things up the way it should have been in
> the first place as necessary). The alternative is that catch(...) is really
> much more fragile/dangerous than a lot of people think anyhow. Besides,
> considering all the goodness that comes out of adhering to a strict strategy
> of inheriting all exceptions from std::exception (all C++ std library
> exceptions already follow this paradigm too), what possible downside is
> there to doing this, aside from having to type a few more characters to
> define a real class definition instead of throwing an int?
>

The catch here is that this relies on what no one would likely argue
against as a good programming technique, but which there is also no
possible way to enforce.  Thus the catch here is that this relies on
an assumption that is not guaranteed to always be safe to make.  In a
perfect world this might be a valid assumption, but in reality it's
better to be safe than sorry.

Finally, even if we could force everyone everywhere forever and always
to use only exceptions derived from std::exception, would that not be
a pretty basic violation of the C++ philosophy of letting the
developer decide what is appropriate by never imposing a
one-size-fits-all this-is-the-only-conceivable solution?

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]