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/