[ Home | CW Bug Reports | Mail ]

LModelObject::GetModelToken() error処理
Subject: BUG -- PP1.9.3 LModelObject::GetModelToken() error handling problem
 
---------------------------------------------------------------------------
 
METROWERKS PRODUCT AND USAGE SECTION
 
Product name :            [ CodeWarrior Professional ]
Product version :         [ Pro 4 ]
Component name :          [ PowerPlant 1.9.3]
Generating:               [ Mac OS 68K / Mac OS PowerPC ]
Purpose:                  [ application ]
 
---------------------------------------------------------------------------
 
BUG DESCRIPTION SECTION
 
Reason for this report:   [ incorrect program feature ]
Bug severity:             [ executes incorrectly ]
Reproducibility:          [ always ]
Problem summary:
 
LModelObject::GetModelToken() should not throw here. If the
LModelObject has DefaultSubModel and failed to get a ModelToken from
it, this always throws.
 
                                    //  "this" model object
     if (outToken.descriptorType == typeNull) {
        try {
            GetModelTokenSelf(inModelID, inKeyForm, inKeyData, outToken);
        }
 
        catch (ExceptionCode inErr) {
            err = (OSErr) inErr;
        }
 
        catch (...) {
            err = errAENoSuchObject;
        }
 
        //  Fall through
    }
 
//    if (err != noErr) {             // Error getting token
//       Throw_(err);
//    }
 
The better code is the following.
If both defaultModel and thisModel failed, it is the real error.
And I think you should add the Handle size comparison as a precaution.
 
void    LModelObject::GetModelToken(DescType        inModelID,
                                    DescType        inKeyForm,
                                    const AEDesc&   inKeyData,
                                    AEDesc&         outToken) const
{
OSErr   defaultModelErr  = noErr;
OSErr   thisModelErr     = noErr;
AEDesc  originalOutToken = outToken;
 
    Assert_(   outToken.descriptorType == typeNull
            || outToken.descriptorType == type_ModelToken
            || outToken.descriptorType == typeAEList);
 
    const SInt32    orgHandleSize = outToken.dataHandle ?
                                ::GetHandleSize(outToken.dataHandle) : 0;
 
                                    //  Recursively try default submodel(s)
    if (GetDefaultSubModel() != nil) {
        StDisableDebugThrow_();     // Ok to fail
 
        try {
            GetDefaultSubModel()->GetModelToken(inModelID,inKeyForm,
                                                inKeyData,outToken);
        }
        catch (ExceptionCode inErr) {
            defaultModelErr = (OSErr)inErr;
        }
        catch (...) {
            defaultModelErr = errAENoSuchObject;
        }
 
        //  Fall through
    }
                                    //  "this" model object
    if (outToken.descriptorType == typeNull) {
        try {
            GetModelTokenSelf(inModelID,inKeyForm,inKeyData,outToken);
        }
        catch (ExceptionCode inErr) {
            thisModelErr = (OSErr)inErr;
        }
        catch (...) {
            thisModelErr = errAENoSuchObject;
        }
 
        //  Fall through
    }
 
    if ((defaultModelErr != noErr) && (thisModelErr != noErr)) {
        ThrowOSErr_(thisModelErr);
    }
 
    const SInt32    outHandleSize = outToken.dataHandle ?
                                ::GetHandleSize(outToken.dataHandle) : 0;
 
    //  If the outToken has not changed since entry to this function,
    //  then we didn't get a valid token. This is an error.
 
    if (   (outToken.descriptorType == originalOutToken.descriptorType)
        && (outToken.dataHandle == originalOutToken.dataHandle)
        && (outHandleSize == orgHandleSize)) {
        ThrowOSErr_(errAENoSuchObject);
    }
}


この Pageは MacOS X + Radio UserLand で作っています。