c_excpt(4)c_excpt(4)NAME
c_excpt.h - Header file defining structured exception handling key‐
words, intrinsics, and structures for the C language compiler
SYNOPSIS
#include <excpt.h> /* includes c_excpt.h */
DESCRIPTION
The c_excpt.h header file defines the keywords, intrinsic functions,
and structures the C language compiler uses to set up a structured
exception handler or termination handler.
Structured Exception Handling
The syntax for a structured exception handler is as follows:
try {
try-body
}
except (exception-filter) {
exception-handler
}
The try-body is the code, expressed as a compound statement, that the
exception handler protects. The try body can be a block of statements
or a set of nested blocks. If an exception occurs while the try body
is executing, exception handling code evaluates the exception-filter to
determine whether to transfer control to the try body's exception-han‐
dler, continue the search for a handler in some outer-level try body,
or continue normal execution.
A program can explicitly initiate an application-specific exception by
calling exc_raise_exception or exc_raise_status_exception. These func‐
tions allow the calling procedure to specify information that describes
the exception. A program can also install a special signal handler,
exc_raise_signal_exception, that converts a signal to an exception,
invoking the exception dispatcher to search for any frame-based excep‐
tion handlers that have been established. In this case, the code
reported to the handler has EXC_SIGNAL in its facility field and the
signal value in its code field. See the Calling Standard for Alpha
Systems and the exception_intro(3) and its associated reference pages
for instructions on how to use exception management routines.
The exception-filter is an expression associated with the exception
handler that guards a given try body. It can be a simple expression or
can invoke a function that evaluates the exception. An exception filter
must evaluate to one of the following integral values: < 0 (EXCEP‐
TION_CONTINUE_EXECUTION)
The exception dispatcher dismisses the exception and resumes the thread
of execution that was originally disrupted by the exception. If the
exception is noncontinuable, the dispatcher raises a STATUS_NONCONTINU‐
ABLE_EXCEPTION exception. 0 (EXCEPTION_CONTINUE_SEARCH)
The exception dispatcher continues to search for a handler, first in
any try...except blocks in which the current one might be nested, and
then in the try..except blocks defined in the procedure frame preceding
the current frame on the runtime stack. If a filter chooses not to han‐
dle an exception, it typically returns this value. > 0 (EXCEPTION_EXE‐
CUTE_HANDLER)
The exception dispatcher transfers control to the exception handler,
and execution continues in the frame on the runtime stack in which the
handler is found. This process, known as handling the exception,
unwinds all procedure frames below the current frame and causes any
termination handlers established within those frames to execute.
Note that you can use a comma to make assignments within the filter
expression. For instance:
except((e=exception_code()) == EXC_VALUE(EXC_SIGNAL, SIGILL) ? 1 :
(printf("unexpected signal exception code 0x%lx0, e),0))
{
/* exception handler */
} Two intrinsic functions are allowed within the exception filter
to access information about the exception being filtered:
long exception_code();
Exception_info_ptr exception_info();
exception_code returns the exception code. The excpt.h include file
defines the exception code formats supported by the operating system.
It also provides symbolic constants for the facility component of Tru64
UNIX-format codes, definitions of system internal exception codes, and
a macro, EXC_VALUE, that allows the definition of application-specific
exception codes. See excpt(4) and the Calling Standard for Alpha Sys‐
tems for additional discussion of exception codes.
exception_info returns a pointer to an EXCEPTION_POINTERS structure.
Using this pointer, you can access the machine state at the time of the
exception. The exception information structure is defined as follows:
typedef struct _EXCEPTION_POINTERS {
system_exrec_type* ExceptionRecord;
PCONTEXT ContextRecord;
EXCEPTION_DISPOSITION Disposition;
DISPATCHER_CONTEXT *DispatcherContext;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *Exception_info_ptr;
An exception record, as defined in the excpt.h include file, describes
an exception. In addition to an exception code, an exception record
contains flags that identify the circumstances under which a handler is
called (for instance, whether an unwind operation is in progress or
whether the exception is continuable). excpt.h defines macros that
allow a handler to test the value of these flags.
A context record, also defined in excpt.h, provides information about
the establisher of an exception handler (such as the PC where control
left the establisher). This information allows the exception dis‐
patcher to properly dispatch the exception. An exception disposition is
a value returned by an exception handler to indicate to the exception
dispatcher whether it should dismiss an exception, continue the search
for an exception handler, or perform some special action. Both the con‐
text record and exception disposition are discussed in greater detail
in excpt(4) and the Calling Standard for Alpha Systems. The calling
standard also discusses the circumstances under which a handler can
modify exception records and context records.
The exception_code intrinsic function can be used within an exception
filter and exception handler. The exception_info function can only be
used within an exception filter. However, the filter can store the
information returned by the function and make it subsequently available
to the exception handler. If you need to refer to exception structures
outside of the filter, you must copy them as well since their storage
is valid only during the execution of the filter.
When an exception occurs, the exception dispatcher virtually unwinds
the runtime stack until it reaches a frame for which a handler has been
established. The dispatcher initially searches for an exception handler
in the stack frame that was current when the exception occurred. If
the handler is not in this stack frame, the dispatcher virtually
unwinds the stack (in its own context), leaving the current stack frame
and any intervening stack frames intact until it reaches a frame that
has established an exception handler. It then executes the exception
filter associated with that handler. Note that, during this phase of
exception dispatching, the dispatcher has only virtually unwound the
runtime stack; all call frames that may have existed on the stack at
the time of the exception are still there. If it cannot find an excep‐
tion handler, or if all handlers reraise the exception, the exception
dispatcher invokes the system last-chance handler.
By treating the exception filter as if it were a Pascal-style nested
procedure, exception handling code evaluates the filter expression
within the scope of the procedure that includes the try...except con‐
struct. This allows the filter expression to access the local vari‐
ables of that procedure, even though the exception may have occurred in
a different procedure.
Prior to executing an exception handler (for instance, if an exception
filter returns EXCEPTION_EXECUTE_HANDLER), the exception dispatcher
performs a real unwind of the runtime stack, executing any termination
handlers established for try...finally blocks that terminated as a
result of the transfer of control to the exception handler. Only then
does the dispatcher calls the exception handler.
The exception-handler is a compound statement that deals with the
exception condition. It executes within the scope of the procedure that
includes the try...except construct and can access its local variables.
A handler can respond to an exception in several different ways,
depending on the nature of the exception. For instance, it can log an
error or correct the circumstances the led to the exception being
raised.
Either an exception filter or exception handler can take steps to mod‐
ify or augment the exception information it has obtained and ask the C-
language exception dispatcher to deliver the new information to excep‐
tion code established in some outer try body or prior call frame. This
activity is more straightforward from within the exception filter,
which operates with the frames of the latest executing procedures --
and the exception context -- still intact on the runtime stack. The
filter simply completes its processing by returning a 0 to the dis‐
patcher to request the dispatcher to continue its search for the next
handler. For an exception handler to trigger a previously-established
handler, it must raise another exception, from its own context, that
the previously-established handler is equipped to handle.
A procedure (or group of interrelated procedures) can contain any num‐
ber of try...except constructs, and can nest these constructs. If an
exception occurs within the try...except block, the system invokes the
exception handler associated with that block.
Termination Handling
The Tru64 UNIX C language compiler allows you to ensure that whenever
control is passed from a guarded body of code, a specified block of
termination code is also executed. The termination code is executed
regardless of how the flow of control leaves the guarded code. For
example, a termination handler can guarantee that clean-up tasks are
performed even if an exception or some other error occurs while the
guarded body of code is executing.
The syntax for a termination handler is as follows:
try {
try-body
}
finally {
termination-handler
}
The try-body is the code, expressed as a compound statement, that the
termination handler protects. The try body can be a block of statements
or a set of nested blocks. It can include the following statement,
which causes an immediate exit from the block and execution of its ter‐
mination handler:
leave;
The termination-handler is a compound statement that executes when the
flow of control leaves the guarded try body, regardless of whether the
try body terminated normally or abnormally. The guarded body is con‐
sidered to have terminated normally when the last statement in the
block is executed (that is, when the body's closing "}" is reached).
Use of the leave statement also causes a normal termination. The
guarded body terminates abnormally when the flow of control leaves it
by any other means: for example, due to an exception, or due to a con‐
trol statement such as return, goto, break or continue.
A termination handler can call the following intrinsic function to
determine whether the guarded body terminated normally or abnormally.
int abnormal_termination();
The abnormal_termination function returns 0 if the try body completed
sequentially; otherwise, it returns 1.
The termination handler itself may terminate sequentially or by a jump
out of the handler. If it terminates sequentially (by reaching the
closing "}"), subsequent control flow depends on how the try body ter‐
minated, as follows: If the try body terminated normally, execution
continues with the statement following the complete try...finally
block. If the try body terminated abnormally with an explicit jump out
of the body, the jump is completed. However, if the jump exits the
body of one or more containing try...finally statements, their termi‐
nation handlers are invoked before control is finally transferred to
the target of the jump. If the try body terminated abnormally due to
an unwind, a jump to an exception handler, or by an exc_longjmp, con‐
trol is returned to the runtime, which will continue invoking termina‐
tion handlers as required before jumping to the target of the unwind.
Like exception filters, termination handlers are treated as Pascal-
style nested procedures, and are executed without the removal of frames
from the runtime stack. A termination handler can thus access the
local variables of the procedure in which it is declared.
Note that there is a performance cost in the servicing of abnormal ter‐
minations, inasmuch as abnormal terminations (and exceptions) are con‐
sidered to be outside the normal flow of control for most programs.
Keep in mind that explicit jumps out of a try body are considered
abnormal termination. Normal termination is the simple case and costs
less at runtime. In some instances, you can avoid this cost by replac‐
ing a jump out of a try body with a leave statement (which transfers
control to the end of the innermost try body) and testing a status
variable after completion of the entire try...finally block.
A termination handler itself may terminate nonsequentially (for
instance, to abort an unwind) by means of a transfer of control (for
instance, a goto, break, continue, return, exc_longjmp, or the occur‐
rence of an exception). If this transfer of control exits another
try...finally block, its termination handler will execute.
NOTES
The try body, exception handler, and termination handler are compound
statements and thus must each be enclosed in braces ({}).
You must not jump into a try body, exception handler, or termination
handler when control is outside the body or handler.
You cannot define a procedure or function within a try...except or
try...finally block, although the sole contents of the block might be a
procedure or function.
If an exception handler within a try...except block contains another
try...except block, and the exception_code() function is invoked within
the exception filter or exception handler for the latter block, it
returns the most recent exception code. If the original handler later
invokes the intrinsic, its effects are undefined.
The compiler will disable a number of optimizations in order to ensure
the integrity of try...except and try...finally blocks.
FILES
Defines data structures supporting the exception handling system.
excpt.h includes c_excpt.h.
RELATED INFORMATION
Functions: exception_intro(3), exception_dispatcher(3), unwind(3),
exc_resume(3), signal(2), sigaction(2).
Files: excpt(4), signal(4).
Calling Standard for Alpha Systems
delim off
c_excpt(4)