
Adobe Acrobat SDK
Handling Exceptions
Developing Plug-ins and Applications
Using register variables 217
exception handler will restore the incorrect calling environment and lead to unpredictable results, as
shown in the following example:
{
DURING /* Places one frame on the exception stack */
pdoc = AVDocGetPDDoc(avdoc);
DURING /* Places a second frame on the stack */
rootBm = PDDocGetBookmarkRot(pdDoc);
if (!PDBookmarkIsValid(rootBm)){
E_RTRN_VOID
/*
Returning here interferes with the exception stack
because two frames have been placed on the stack
and E_RTRN_VOID only clears one of them before
returning
*/
}
pdAction = PDBookMarkGetAction(parentBm);
HANDLER
AVAlertNote("Bad AVDoc");
return (1);
/*
Returning here interferes with the exception stack
because there is still a frame on the stack from
the outer DURING macro and it will not be cleared
before the function returns
*/
END_HANDLER
HANDLER
AVAlertNote("Bad PDDoc");
END_HANDLER
}
Using register variables
The
DURING
and
HANDLER
macros use the standard C
setjmp/longjmp
mechanism. The
DURING
macro calls
setjmp
. An exception results in a
longjmp
to the context that was saved by the most recent
setjmp
. When a
longjmp
occurs, all registers, including those containing variables the compiler
optimized into register variables, are restored to the values they held when the
setjmp
occurred.
As a result, the state of local variables that have been optimized into registers is unpredictable when the
exception handler is invoked. To avoid this situation, declare all variables that are set in the main body of
the code and used in the exception handler or beyond (if the handler lets execution continue) as volatile.
This ensures that they are never optimized into register variables, but are always referenced from memory.
When using the
volatile
statement, be sure to place the keyword in the correct location, for example:
volatile myStruct* p = 0;
declares the instance of the structure to be volatile, while
myStruct* volatile p = 0;
declares the pointer itself to be volatile. In general, the second version is the one to use.