[an error occurred while processing this directive]

HP OpenVMS Systems

C++ Programming Language
Content starts here HP C++

HP C++
User's Guide for OpenVMS Systems


Previous Contents Index


Chapter 6
Handling C++ Exceptions

Exception handling is a C++ language mechanism for handling unusual program events (not just errors). On OpenVMS systems, HP C++ implements the exception handling model described in the C++ International Standard.

This includes support for throwing and catching exceptions, and calling the terminate() and unexpected() functions. C++ exception-handling support is implemented using functions and related OpenVMS systemservices that comprise the OpenVMS condition-handling facility. Hence, C++ exception-handling support is fully integrated with existing uses of the OpenVMS condition handling facility.

6.1 Compiling with Exceptions

Because exceptions are enabled by default, you need not specify the /EXCEPTIONS qualifier whenever you compile the program.

For more information about the /EXCEPTIONS qualifier see Appendix A.

Note

If you are programming in kernel mode or creating a protected shareable image, C++ exception handling is not supported. To ensure that your code does not contain constructs that trigger C++ exceptions or to prevent errors from occurring during initialization of exception handlers at runtime, specify the /NOEXCEPTIONS qualifier when compiling.

6.2 Linking with Exceptions (ALPHA ONLY)

If any files in your program contain throw expressions, try blocks, or catch statements, or if any files in your program are compiled with the exceptions, you must link your program using the cxxlink facility (see Section 1.3 for more information on this facility). For example:


 $ cxxlink my_prog.obj 

Using the cxxlink facility ensures that the run-time support for exceptions ( sys$library:libcxxstd.olb ) is linked into your program.

Linking with /NOSYSSHR (OpenVMS Version 6.2)

If you are running OpenVMS Version 6.2 or later, and you want to link using the /NOSYSSHR qualifier, you must specify a linker options file on your cxxlink command. Otherwise, your link might fail because of undefined symbol references.

The linker options file should contain the following:


 sys$share:librtl.exe/shar 

For example, if cxx_exc.opt is your linker options file containing the above line, then a possible link command would be:


 $ cxxlink my_prog.obj, my_disk:[my_dir]cxx_exc.opt/opt 

Because the necessary run-time libraries are not provided in object format on OpenVMS Version 6.1 and earlier releases, linking with /NOSYSSHR on those systems is not recommended.

For more information about linking with /NOSYSSHR and about OpenVMS linker options files see the OpenVMS Linker Utility Manual

6.3 The terminate() and unexpected() Functions

The unexpected() and set_unexpected() functions are implemented as defined in the ISO/IEC International Standard.

The terminate() and set_terminate() functions are implemented as defined in the ISO/IEC International Standard. By default, the terminate() function raises the OpenVMS condition cxxl$_terminate , and then calls the abort() function.

On Alpha systems, no stack unwinding is done by the terminate() function. Hence, no destructors are called for constructed objects when a thrown exception results in a call of the terminate() function. Instead, the program is terminated.

On I64 systems, stack unwinding is done.

If a C++ function is called from a program in which the main function is not C++, terminate() is not called. Instead, the call stack points to the point of the throw.

6.4 C++ Exceptions and Other Conditions

Because C++ exceptions are implemented using the OpenVMS condition handling facility, C++ modules will work properly when they are part of a program that makes other uses of OpenVMS condition handling.

The raising and handling of an OpenVMS condition can result in the destruction of C++ automatic objects. If the handling of an OpenVMS condition results in an unwind through a C++ function's stack frame, then destructors will be called for automatic objects declared in that stack frame, just as if a C++ exception had been caught by a handler in an outer stack frame.

The C++ exception handling facility can also be used to catch OpenVMS conditions that are raised independently of C++ throw expressions. Except for those OpenVMS conditions that result in the delivery of signals, a C++ catch(...) handler will catch both C++ thrown exceptions and OpenVMS conditions. (For more information about OpenVMS conditions that result in the delivery of signals, see Section 6.5.)

You can use the data type struct chf$signal_array & , defined in the system header file chfdef.h , to catch OpenVMS conditions and to obtain information about the raised conditions. The C++ exceptions support transfers control to catch(struct chf$signal_array &) handlers when it determines that an OpenVMS condition was raised independently of a C++ throw statement.

If the catch (struct chf$signal_array &) handler specifies a class object, then the C++ exceptions support sets the class object to be a reference to the raised OpenVMS condition's signal argument vector. In the following example, obj.chf$l_sig_name will have the value 1022 when it is printed:


#include <chfdef.h> 
#include <iostream.hxx> 
#include <lib$routines.h> 
main () 
{ 
    try { 
        lib$signal (1022); 
    } catch (struct chf$signal_array &obj) { 
        cout << obj.chf$l_sig_name << endl; 
    } 
} 

A catch(struct chf$signal_array &) handler will also catch a thrown object that is explicitly declared to be of type struct chf$signal_array & . In this case, the value of the catch handler's object is determined by the originally thrown object, not the OpenVMS signal argument vector.

You can also use the data type struct chf$signal_array * to catch both OpenVMS conditions and objects explicitly declared to be of type struct chf$signal_array * . If a catch(struct chf$signal_array *) handler specifies an object, then that object becomes a pointer to the thrown object.

For more information about OpenVMS conditions, see the OpenVMS Calling Standard.

6.5 C++ Exceptions and Signals (ALPHA ONLY)

Certain OpenVMS conditions (as described in the HP C Run-Time Library Reference Manual for OpenVMS Systems) normally result in the delivery of signals. These signals can be processed using the signal handler mechanism described in the HP C Run-Time Library Reference Manual for OpenVMS Systems.

You can call the following run-time function in conjunction with the /EXCEPTION=IMPLICIT qualifier to cause these OpenVMS conditions to be treated as exceptions, instead of signals:


cxxl$set_condition(condition_behavior signal_or_exc) 

This can be done by putting the following call in your program:


#include <cxx_exception.h> 
...
cxxl$set_condition (cxx_exception); 

Caution

You must specify /EXCEPTION=IMPLICIT; otherwise, the code that would normally cause a signal and now causes an exception might be moved out of the try block.

After your program calls the cxxl$set_condition (cxx_exception) function you can then catch these exceptions using any of the following handlers:

catch(struct chf$signal_array &)
catch(struct chf$signal_array *)
catch(...)

To revert back to the default signal behavior, you can make the following call:


cxxl$set_condition (unix_signal); 

Caution

Avoid doing a C++ throw from a C signal handler or VMS exception handler because this action could terminate your program.

The following are defined in the header file cxx_exception.h :

The cxxl$set_condition() function
The condition_behavior {unix_signal=0, cxx_exception=1 } enumeration type

The cxxl$set_condition function returns the previous setting. This function affects all threads in a process.

6.6 C++ Exceptions with setjmp and longjmp

If a C++ function calls either the setjmp() or the longjmp() routine, C++ exceptions support is disabled for that function. This means the following:

  • No exceptions can be caught by the function's catch handlers.
  • No destructors are called for the function's automatic data if an exception propagates through the function.
  • The unexpected() function is not called for that function.
  • If either setjmp() or longjmp() is called from main() , then terminate() is not called for an unhandled exception.

6.7 C++ Exceptions, lib$establish and vaxc$establish

If a C++ function calls either the lib$establish() or the vaxc$establish() routine, then C++ exceptions support is disabled for that function. This means the following:

  • No exceptions can be caught by the function's catch handlers.
  • No destructors are called for the function's automatic data if an exception propagates through the function.
  • The unexpected() function is not called for that function.
  • If either lib$establish() or vaxc$establish() is called from main() , then terminate() is not called for an unhandled exception.

6.8 Performance Considerations

The compiler optimizes the implementation of exception handling for normal execution, as follows:

  • Applications that do not use C++ exceptions and are compiled with the /NOEXCEPTIONS qualifier incur no run-time or image size overhead.
  • Applications compiled with exceptions enabled that have try blocks or automatic objects with destructors incur an increase in image size.
  • As much as possible, the run-time overhead for exceptions is incurred when throwing and catching exceptions, not when entering and exiting try blocks normally.

6.9 C++ Exceptions and Threads

C++ exceptions are thread safe. This means that multiple threads within a process can throw and catch exceptions concurrently. However, exceptions do not propagate from one thread to another, nor can one thread catch an exception thrown by another thread.

The set_terminate() and set_unexpected() functions set the terminate() and unexpected() handlers for the calling thread. Therefore, each thread in a program has its own terminate() and unexpected() handlers.

If you want every thread in your program to use the same nondefault terminate() or unexpected() handlers, then you must call the set_terminate() and set_unexpected() functions separately from each thread.

By default, the C++ exception package allows the delivery of the CMA$_EXIT_THREAD condition, but not the CMA$_ALERTED condition. This latter condition is raised to a thread that is being cancelled. The following routine ( test_thread ) allows an application to control the default behavior of these two conditions:


int cxxl$catchable_condition (int condition, int on_or_off); 

The condition is either CMA$_EXIT_THREAD or CMA$_ALERTED. A value of zero means the program does not want the condition to result in a catch clause receiving the exception. This is the default behavior for CMA$_ALERTED. A value of nonzero means the program does want the condition to result in the catch clause of the thread to receive control when the exception is raised. The behavior is undefined for any other condition value passed.

The return value of the routine is the previous setting for the passed condition value:


#include <pthread.h> 
    #include <cxx_exception.h> 
    #include <cma$def.h> 
    ... 
 
    static void *test_thread (...) { 
    ... 
    try { 
    ... 
    } catch (chf$signal_array *p) { 
       switch (p->chf$l_sig_name) 
       { 
           case CMA$_ALERTED: 
               printf ("  test_thread caught CMA$_ALERTED\n"); 
               break; 
           default: 
               printf ("  test_thread caught (%d)\n", p->chf$l_sig_name); 
               break; 
} 
    } 
 
    } 
 
 
    int main () { 
    ... 
       if (cxxl$catchable_condition(CMA$_ALERTED,1)) 
            printf ("  CMA$_ALERTED continues to be catchable\n"); 
       else printf ("  CMA$_ALERTED is now catchable\n"); 
 
    ... 
       pthread_create (&thread, ...); 
    ... 
       pthread_cancel (thread); 
    ... 
    } 

For more information about threads, see the Guide to DECthreads manual.

6.10 Debugging with C++ Exceptions (ALPHA ONLY)

You can use the OpenVMS Debugger set break/exception command to set a breakpoint when an exception is thrown. You can use the show calls command to determine the location where the exception was thrown.


Previous Next Contents Index