[Up: C++ mapping]
[Previous: Modules] [Next: Time Service]

Subsections

Exceptions

Due to the limited support for exceptions in earlier versions of the GNU C++ compiler (namely gcc 2.7.2) MICO supports several kinds of exception handling:

Two common problems with exception handling are ``catching by base classes'' and ``exceptions in shared libraries'':

Which kind of exception handling is used is determined by the capabilities of the C++ compiler and command line options passed to the configure script. By default CORBA compliant exception handling will be selected if the C++ compiler supports catching by base classes, otherwise MICO specific exception handling is selected if the compiler supports exception handling at all. If exceptions in shared libraries do not work then no exception handling is selected for code in shared libraries. You can enforce MICO specific exception handling by specifying -disable-std-eh as a command line option to configure. You can disable exception handling by specifying -disable-except as a command line option to configure.

You can find out about the exception handling support of your MICO binaries by running the IDL-Compiler with the -config command line option:

  $ idl --config
  MICO version: 2.2.7
  supported CORBA version: 2.2
  exceptions: CORBA compliant
  modules are mapped to: namespaces
  STL is: miniSTL
  SSL support: no
  loadable modules: yes

The following sections go into detail about each of the exception handling modes supported by MICO.

CORBA Compliant Exception Handling

As the name already indicates this exception handling mode is conformant to the CORBA specification. You can use throw to throw exceptions. Exceptions are caught by specifying the exact type or one of the base types of the exception. Here are some examples:

  // throw CORBA::UNKNOWN exception
  throw CORBA::UNKNOWN();

  // catch CORBA::UNKNOWN exception
  try {
    ...
  } catch (CORBA::UNKNOWN &ex) {
    ...
  }

  // catch all system exceptions (including CORBA::UNKNOWN)
  try {
    ...
  } catch (CORBA::SystemException &ex) {
    ...
  }

  // catch all user exceptions (wont catch CORBA::UNKNOWN)
  try {
    ...
  } catch (CORBA::UserException &ex) {
    ...
  }

  // catch all exceptions (including CORBA::UNKNOWN)
  try {
    ...
  } catch (CORBA::Exception &ex) {
    ...
  }

If an exception is thrown but not caught MICO will print out a short description of the exception and terminate the process.

MICO Specific Exception Handling

This kind of exception handling has been invented for C++ compilers that do not support catching by base classes. For example it is quite common to catch all system exceptions. Since catching CORBA::SystemException & does not work one would have to write one catch clause for each of the 30 system exceptions. To work around this problem the function mico_throw() and special _var types have been introduced.

You must not use the throw operator directly to throw an exception, instead you should use the function mico_throw() defined in mico/throw.h, which is automatically included by IDL compiler generated code:

  // ok
  mico_throw (CORBA::UNKNOWN());

  // wrong
  throw CORBA::UNKNOWN();

will throw the CORBA system exception UNKNOWN. User defined exceptions are thrown the same way.

Exceptions are always caught by reference using the _var types. System exceptions must be caught by SystemException_var:

  // ok
  try {
    ...
    mico_throw (CORBA::UNKNOWN());
    ...
  } catch (CORBA::SystemException_var &ex) {
    ...
  }

  // wrong
  try {
    ...
    mico_throw (CORBA::UNKNOWN());
    ...
  } catch (CORBA::UNKNOWN_var &ex) {
    ...
  }

  // wrong
  try {
    ...
    mico_throw (CORBA::UNKNOWN());
    ...
  } catch (CORBA::Exception_var &ex) {
    ...
  }

Sometimes it is necessary to know exactly which system exception has been thrown:

  // ok
  try {
    ...
    mico_throw (CORBA::UNKNOWN());
    ...
  } catch (CORBA::SystemException_var &sys_ex) {
    if (CORBA::UNKNOWN *ukn_ex = CORBA::UNKNOWN::_narrow (sys_ex)) {
      // something1
    } else {
      // something2
    }
  }

  // wrong
  try {
    ...
  } catch (CORBA::UNKNOWN_var &ukn_ex) {
    // something1
  } catch (CORBA::SystemException_var &other_ex) {
    // something2
  }

In contrast to system exceptions a user exception X must be caught by X_var (i.e., not by UserException_var):

  // ok
  try {
    ...
    mico_throw (SomeExcept());
    ...
  } catch (SomeExcept_var &some_ex) {
    ...
  }

  // wrong
  try {
    ...
    mico_throw (SomeExcept());
    ...
  } catch (CORBA::UserException_var &usr_ex) {
    ...
  }

  // wrong
  try {
    ...
    mico_throw (SomeExcept());
    ...
  } catch (CORBA::Exception_var &ex) {
    ...
  }

It is possible to write code that works both with CORBA compliant exception handling and MICO specific exception handling. For this one should follow the instructions in this section but replace _var by _catch. In MICO specific exception handling mode X_catch is typedef'ed to X_var, in CORBA compliant exception handling mode X_catch is typedef'ed to X. Furthermore each exception X provides an overloaded -> operator so that you can use -> to access the exception members in the catch body independent of the exception handling mode. Here is an example:

  // throw
  mico_throw (CORBA::UNKNOWN());

  // catch
  try {
    ...
  } catch (CORBA::SystemException_catch &ex) {
    cout << ex->minor() << endl;
  }

If an exception is thrown but not caught MICO will print out a short description of the exception and terminate the process.

No Exception handling

Some C++ compilers do not properly support exceptions in shared libraries, others do not support exceptions at all. In these cases exception handling is not available in shared libraries or not available at all, respectively.

Exception handling related C++ keywords (try, throw, catch) cannot be used in this mode. mico_throw() can be used but will only print out a short description of the passed exception and terminate the process.


[Previous: Modules] [Next: Time Service]
[Up: C++ mapping]

Frank Pilhofer
2001-09-28