On 2006-06-11, P REEDER <[EMAIL PROTECTED]> wrote:
> I have previously used code which uses ErrTry without problems, though I do
> not recall how much I tested throwing and catching errors.   I have now
> written some code using ErrTry which I have discovered crashes if an error
> is thrown under OS 3 or 4, but not OS 5.  It does not crash if no error
> is thrown.  The code looks fine to me (see below), but has anyone any
> suggestions based on the OS version?
>
>
> void OutStreamDelete(StreamIndex d) {
>       Err err = errNone;
>       Err err2;
>       
>       if (d < 0 || d > NUM_DESCR_SLOTS) {
>               HostTraceGlueOutputT(appErrorClass, "slot %u does not exist; 
> can't delete", d);
>               ErrThrow(__LINE__*65536 + appErrorBadParam);
>       }
>       
>       if (descriptors[d] == NULL) {
>               //ErrThrow(__LINE__*65536 + appError);
>               HostTraceGlueOutputT(appErrorClass, "stream %hu already 
> deleted", d);
>               return;
>       }
>       
>       //if (descriptors[d]->outStreamRef == 0) 
>       //      return;
>       
>       if (gNoAudio) {
>               HostTraceGlueOutputT(appErrorClass, "deleting fictitious output 
> stream %hu   [%lx]", d, descriptors[d]);
>       } else {
>               HostTraceGlueOutputT(appErrorClass, "deleting output stream %hu 
>   [%lx]", d, descriptors[d]);
>               err = SndStreamDelete(descriptors[d]->outStreamRef);
>       }       
>       //outDescrP->outStreamRef = 0;
>       err2 = MemPtrFree(descriptors[d]);
>       descriptors[d] = NULL;
>       
>       if (err) {
>               ErrThrow(__LINE__*65536 + err);
>       } else if (err2) {
>               ErrThrow(__LINE__*65536 + err2);
>       }               
> }
>
>
> void DestroyManyStreams(void) {
>       StreamIndex d;
>       char sysMessage[80];
>       
>       ErrTry {
>               for (d=0; d<20; ++d) {
>                       OutStreamDelete(d);
>                       //DisplayMessage(appLogNormal, "deleted stream, index 
> %u", d);
>               }
>       } ErrCatch(err) {
>               SysErrString(err & 0xffff, sysMessage, 30);
>               DisplayMessage(err & 0xffff, "%s at line %ld, caught in %s",
>                                          sysMessage, err >> 16, __FILE__);
>       } ErrEndCatch
>               
>       DisplayMessage(appLogNormal, "end multi-stream destruction test");
> }
>
>
>
> [Don't worry about the references to audio streams -- gNoAudio is set to
> true if there is no sampled audio hardware, which of course there is not
> under OS 3 or 4.]

First ErrThrow() can only be called from within an ErrTry block. This is 
because the ErrTry/ErrCatch/ErrThrow are based on setjmp/longjmp.
The best source for information are the comments in the header file 
ErrorBase.h from the PalmSource SDK. See below,
================================================================================
 * Exception Handling
 *
 *    This unit implements an exception handling mechanism that is similar
 *    to "real" C++ Exceptions. Our Exceptions are untyped, and there
 *    must be one and only one Catch block for each Try block.
 *
 * Try/Catch Syntax:
 *
 *    ErrTry {
 *       // Do something which may fail.
 *       // Call ErrThrow() to signal failure and force jump
 *       // to the following Catch block.
 *    }
 *
 *    ErrCatch(inErr) {
 *       // Recover or cleanup after a failure in the above Try block.
 *       // "inErr" is an ExceptionCode identifying the reason
 *       // for the failure.
 *
 *       // You may call Throw() if you want to jump out to
 *       // the next Catch block.
 *
 *       // The code in this Catch block does not execute if
 *       // the above Try block completes without a Throw.
 *
 *    } ErrEndCatch
 *
 *    You must structure your code exactly as above. You can't have a
 *    ErrTry { } without a ErrCatch { } ErrEndCatch, or vice versa.
 *
 *
 * ErrThrow
 *
 *    To signal failure, call ErrThrow() from within a Try block. The
 *    Throw can occur anywhere in the Try block, even within functions
 *    called from the Try block. A ErrThrow() will jump execution to the
 *    start of the nearest Catch block, even across function calls.
 *    Destructors for stack-based objects which go out of scope as
 *    a result of the ErrThrow() are called.
 *
 *    You can call ErrThrow() from within a Catch block to "rethrow"
 *    the exception to the next nearest Catch block.
 *
 *
 * Exception Codes
 *
 *    An ExceptionCode is a 32-bit number. You will normally use
 *    Pilot error codes, which are 16-bit numbers. This allows
 *    plently of room for defining codes for your own kinds of errors.
 *
 *
 * Limitations
 *
 *    Try/Catch and Throw are based on setjmp/longjmp. At the
 *    beginning of a Try block, setjmp saves the machine registers.
 *    Throw calls longjmp, which restores the registers and jumps
 *    to the beginning of the Catch block. Therefore, any changes
 *    in the Try block to variables stored in registers will not
 *    be retained when entering the Catch block.
 *
 *    The solution is to declare variables that you want to use
 *    in both the Try and Catch blocks as "volatile". For example:
 *
 *    volatile long  x = 1;      // Declare volatile local variable
 *    ErrTry {
 *       x = 100;                // Set local variable in Try
 *       ErrThrow(-1);
 *    }
 *
 *    ErrCatch(inErr) {
 *       if (x > 1) {            // Use local variable in Catch
 *          SysBeep(1);
 *       }
 *    } ErrEndCatch
================================================================================
Since PalmOS 5 uses a simulated 68K environment (PACE) I guess you have
been lucky your code did not crash in PalmOS5. Have you run it in any of 
the debug simulators?

HTH

Ton van Overbeek

-- 
For information on using the PalmSource Developer Forums, or to unsubscribe, 
please see http://www.palmos.com/dev/support/forums/

Reply via email to