Topic: A better standard in exception handling


Author: erolfe - Edward Boggis-Rolfe <EROLFE@acxiom.co.uk>
Date: 1998/05/18
Raw View
This message is too late for the recently released C++ standard, but I
hope it  will encourage people to think about implementing some
slightly better thought out exception classes, with a base exception
class that has some basic internationalization features, and perhaps
(you never know) a standard might be made out of it.

I have been writing COM (this may well apply to CORBA as well)
applications for quite a while and I have found that I am always
writing the same code over and over again to handle any exceptions
that may get thrown inside a COM interface function. What I am trying
to do is reduce all this donkey work to one global non exiting
exception handler.

Since the C++ language has been around for quite a while people have
rolled their own implementations of exception classes, as they cannot
wait for a standard exception class to arrive. Some companies also
slightly jumped the gun and their implementations of the STL exception
classes differ slightly from the standard (the 'what' function is
called 'why').

What this then causes is a mess of different exception classes that
need their own special handling in the catch section of an exception
handler. If you are using five different class libraries you may find
that you may have to write five or more different catch statements
plus the ubiquitous dumb catch(...).

To make things even more challenging my current project requires that
the server code is internationally aware, meaning that when a client
logs onto a server it provides a locale in order for the server to
format messages in the right language.

This compounds the issues even further often the error description
function of an exception returns a single byte character string, with
the text statically built into the code - hardly friendly to most of
the world's population. Good example of this is what I have seen in
the Objectspace and RougueWave libraries.

What is needed is for an exception class that expects the handler may
need to go off to a message database somewhere to lookup the right
message. What I am proposing is a database table that consists of a
globally unique exception class ID, a locale ID, a message ID and the
message itself.

A querying SQL statement may look like this:
SELECT message_text FROM errors WHERE classID = x, localeID = y, msgID
= z

If you are interested in cross platform locales have a look at
www.uni-scape.com.

Once the message is then obtained it is then passed back to the
exception class for any additional processing (e.g. sprintf) using
process_message_template.

The base internationalized exception class will look like this

class base_international_exception
{
 virtual int get_message_code();  //Get MessageID
 virtual int get_class_id();   //ID of this class or the class that
threw the exception

 //notice that this function takes Unicode strings
 virtual void process_message_template(  wchar_t* pszMessage_buffer ,
  //destination buffer
  int len,      //buffer length in characters
 wchar_t* pszMessage_template); //template string
 //alternatives could be used with the wstring class
}

Once you have such a class that all your exception classes are based
upon, you could possibly save yourself a fortune when the time comes
when you need to have your application in another language.

Here is what I have done with this approach, here is an exception
hander that I have written for writing COM objects (I guess that
something similar could be useful for CORBA):

template <class A,class B,class C>
long handle2(A*a,void (A::*f)(B,C),B b,C c)
{
     {
          long res = 0;
     }
     try
     {
          res = (a->*f)(b,c);
     }
     catch(my_exception& ex)
     {
          //find the users locale ID from (in this case) the thread
context
          //get the class ID from the exception class
          //get the message ID from the exception class
          //lookup the error message template from the look-up table
          //allow the exception class process the template into the
finished message
          //Send the message text to the user
          return PrepareMessage(&ex);
     }
     catch(...)
     {
          return PrepareMessage(NULL);
     }
     return res;
}

Here is how I use it:

long AddUser(BSTR Name, long* UserID)
{
     return handle2(this, InnerAddUser, Name, UserID); /*line
shortened for brevity sake*/
}

The advantage of this mechanism is that if you have hundreds of
functions to protect, you only need ever write one exception handler
function (thereby making your code smaller and easier to manage).
 What has stumped me is to create a variable length exception handler.
Incidentally I am trying to use a similar construction to this for
launching threads in member functions of C++ classes.

Question: if you cannot escape exceptions, why not use them whenever
your function cannot follow its critical path. If your application is
truly OO you should not have anything to worry about (i.e. protect
anything created on the heap by something managed on the stack or in a
collection object). Your helper functions will never need to return
error messages as exceptions will always be thrown instead, making
much cleaner code.

Edward Boggis-Rolfe

Application Developer
erolfe@acxiom.co.uk
Acxiom UK Ltd.



[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]