Skip to Main Content United States    
PRODUCTS SUPPORT SOLUTIONS SERVICES
COMPAQ SOFTWARE
Compaq C++

Compaq C++
Using Compaq C++ for OpenVMS Alpha


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, Compaq 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 Section 6.3.

Note

If you are programming in kernel mode or creating a protected shareable image, C++ exception handling is not supported. To prevent errors from occuring during initialization of exception handling at runtime, specify the /noexceptions qualifier when compiling.

6.2 Linking with Exceptions

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 /exceptions Qualifier

This section describes the /exceptions qualifier in detail.

/exceptions[=[no]cleanup] (Default)
/noexceptions

Controls whether support for C++ exceptions is enabled or disabled. C++ exceptions with the cleanup option are enabled by default.

When exceptions are enabled, the compiler generates code for throw expressions, try blocks, and catch statements. The compiler also generates special code for main programs so that the terminate() routine is called for unhandled exceptions.

You can control the cleanup of automatic objects during exception processing by using the [no]cleanup option:

  • When /exceptions=cleanup is in effect, the compiler generates cleanup code for automatic objects. As a result, when an exception is handled at run-time and control passes from a throw point to a handler, destructors are called for all automatic objects that were constructed since the try block containing the handler was entered.
  • When /exceptions=nocleanup is in effect, this cleanup code is not generated. You can reduce the size of your executable image by using /exceptions=nocleanup if you want to throw and handle exceptions, but cleanup of automatic objects during exception processing is not important for your application.

Specifying /noexceptions disables C++ exceptions as follows:

  • The compiler diagnoses warnings for throw expressions, try blocks, and catch statements, but may generate code for these constructs.
  • The compiler does not generate cleanup code for automatic objects.
  • The compiler does not generate special code for main programs so that the terminate() function is called for unhandled exceptions.

If any files in your program contain throw expressions, try blocks, or catch statements, or if exceptions are enabled, you must link your program using the CXXLINK facility. See Section 6.2.

6.4 The terminate() and unexpected() Functions

The unexpected() and set_unexpected() functions are implemented as defined in the IS.

By default, the unexpected() function calls the terminate() function.

The terminate() and set_terminate() functions are implemented as defined in the IS. The terminate() function is called if no matching handler is found for a thrown exception. By default, the terminate() function raises the OpenVMS condition cxxl$_terminate , and then calls the abort() function.

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.

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.

The terminate() function is also called in the following additional cases:

  • An exception is thrown by a destructor or copy constructor called from the C++ exceptions handling support.
  • An internal error occurs in the C++ exceptions handling support.

6.5 C++ Exceptions and Other OpenVMS 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.6.)

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.6 C++ Exceptions and Signals

Certain OpenVMS conditions (as described in the Compaq 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 Compaq 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.7 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.8 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.9 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.10 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.

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

6.11 Debugging with C++ Exceptions

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
Buy Online or Call 1.800.888.0220      privacy statement and legal notices 
STORES CONTACT US SEARCH PRODUCTS SOLUTIONS OPTIONS DEVELOPERS