2fmlcalls@kuhub.cc.ukans.edu (05/06/91)
> Even though GetResource couldn'thave found the resource (because > it wasn't there), ResError returned a 0, indicating that nothing > was wrong. Needless to say, the first time I referred to the > resource, I got a Bus Error exception, because I was following > the invalid handle out into La-La Land. > > Why didn't ResError tell me there was a problem? > > --Kurisuto > un020070@vaxa.wvnet.edu I've seen it documented that ResError doesn't always return 0. I think the preferred method is to check the resource hanfter you read it in. Check for nil. if (myRes = nil) then .... or if (myRes^=nil) then ... I've never been clear which is more reliable, the handle or pointer. john calhoun
vrm@blackwater.cerc.wvu.wvnet.edu (Vasile R. Montan) (05/06/91)
I am writing a program which does a lot of reading and writing of resources (but don't we all? :-). I am trying to write the code as defensively as possible, so that if anything goes wrong, the program will continue as gracefully as possible. For example, here is a snip of code from one of my routines: if OkSoFar then {If we've run in to no problems so far, then get the} begin {resource and typecast it to the right type.} Room := RoomHandle(GetResource('ROOM', RoomNum)); OSResult := ResError; {Check for errors.} if OSResult <> 0 then {If there was an error...} begin doOSErr(OSResult); {then post an alert} OkSoFar := False; {and stop trying to finish the procedure} end; end; As you can see, the soundness of the code relies on ResError to tell if anything has gone wrong. However, I tried testing the code by removing the crucial resource and running this code again. Even though GetResource couldn'thave found the resource (because it wasn't there), ResError returned a 0, indicating that nothing was wrong. Needless to say, the first time I referred to the resource, I got a Bus Error exception, because I was following the invalid handle out into La-La Land. Why didn't ResError tell me there was a problem? --Kurisuto un020070@vaxa.wvnet.edu
resnick@cogsci.uiuc.edu (Pete Resnick) (05/07/91)
vrm@blackwater.cerc.wvu.wvnet.edu (Vasile R. Montan) writes: >As you can see, the soundness of the code relies on ResError to >tell if anything has gone wrong. However, I tried testing the >code by removing the crucial resource and running this code again. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As documented, if there is no resource of the type requested when you make a GetResource call, ResError will return noErr, but the handle you get back will be nil. On GetResource calls, always check the handle to see if it was nil. Only use the value of ResError once you have a nil value to figure out what went wrong. myHandle = GetResource(myType, myNumber); if(myHandle == 0L) return(ResError() ? ResError() : resNotFound); That's the way I usually do it. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet/ARPAnet/EDUnet : resnick@cogsci.uiuc.edu BITNET (if no other way) : FREE0285@UIUCVMD
murat@farcomp.UUCP (Murat Konar) (05/07/91)
In article <1696@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes: [preamble and code frag ommitted] >As you can see, the soundness of the code relies on ResError to >tell if anything has gone wrong. However, I tried testing the >code by removing the crucial resource and running this code again. >Even though GetResource couldn'thave found the resource (because >it wasn't there), ResError returned a 0, indicating that nothing >was wrong. Needless to say, the first time I referred to the >resource, I got a Bus Error exception, because I was following >the invalid handle out into La-La Land. > >Why didn't ResError tell me there was a problem? Page 119, Inside Macintosh Volume I sez (and I quote): Note: If you call GetResource with a resource type that isn't in any open resource file, it returns NIL but the ResError function will return the result code noErr. Neat, huh? I got bit by this before too. -- ____________________________________________________________________ Have a day. :^| Murat N. Konar murat@farcomp.UUCP -or- farcomp!murat@apple.com
REEKES@applelink.apple.com (Jim Reekes) (05/08/91)
In article <1991May6.143630.30448@kuhub.cc.ukans.edu>, 2fmlcalls@kuhub.cc.ukans.edu writes: > > > Even though GetResource couldn'thave found the resource (because > > it wasn't there), ResError returned a 0, indicating that nothing > > was wrong. Needless to say, the first time I referred to the > > resource, I got a Bus Error exception, because I was following > > the invalid handle out into La-La Land. > > > > Why didn't ResError tell me there was a problem? > > > > --Kurisuto > > un020070@vaxa.wvnet.edu > > I've seen it documented that ResError doesn't always return 0. I think the > preferred method is to check the resource hanfter you read it in. Check for > nil. > > if (myRes = nil) then .... > > or > > if (myRes^=nil) then ... > > I've never been clear which is more reliable, the handle or pointer. The handle is the reliable check. Testing the pointer only tells you if the handle has been purged, but if you have a nil handle to start with deferencing it will be bad. Consider ResError the reason why you got a nil handle. So, always test for nil and then look at ResError. If you are calling AddResource, UpdateResFile, or other routines that do not return a handle then ResError will be set. Another gottcha is to check ResError after calling HGetState. Otherwise the result is trash, not handle state information so don't call HSetState with it later. Jim Reekes E.O., Macintosh Toolbox Engineering
gft_robert@gsbacd.uchicago.edu (opcode ranger) (05/08/91)
In article <13382@goofy.Apple.COM>, REEKES@applelink.apple.com (Jim Reekes) writes: [...] > Another gottcha is to > check ResError after calling HGetState. Otherwise the result is trash, not handle > state information so don't call HSetState with it later. Check ResError _every_ time you call HGetState, or only on Handles related to resources? Robert -- ============================================================================ = gft_robert@gsbacd.uchicago.edu * generic disclaimer: * "Good tea. = = * all my opinions are * Nice house." = = * mine * -Worf = ============================================================================
hairston@henry.ece.cmu.edu (David Hairston) (05/08/91)
[un020070@vaxa.wvnet.edu (Kurisuto) writes:] [] Even though GetResource couldn'thave found the resource (because [] it wasn't there), ResError returned a 0, indicating that nothing [] was wrong. Needless to say, the first time I referred to the [] resource, I got a Bus Error exception, because I was following [] the invalid handle out into La-La Land. [] [] Why didn't ResError tell me there was a problem? [2fmlcalls@kuhub.cc.ukans.edu writes:] [] I've seen it documented that ResError doesn't always return 0. I think the [] preferred method is to check the resource hanfter you read it in. Check [] for nil. [] ... [] I've never been clear which is more reliable, the handle or pointer. [REEKES@applelink.apple.com (Jim Reekes) writes:] [] The handle is the reliable check. Testing the pointer only tells you if [] the handle has been purged, but if you have a nil handle to start with [] deferencing it will be bad. Consider ResError the reason why you got a [] nil handle. So, always test for nil and then look at ResError. [] ... there's a no-brainer which has worked its way into my code (C example): #define goodHand(x) ((x) && *(x)) which gets used for: realHandle = GetResource(type, index); if (!goodHand(realHandle)) .... as well as for: fooPointer = NewWindow(...); if (!goodHand(&fooPointer)) .... i guess i shouldn't be lazy but it's a no-brainer ... -dave- hairston@henry.ece.cmu.edu
ech@cbnewsk.att.com (ned.horvath) (05/08/91)
From article <12946@pt.cs.cmu.edu>, by hairston@henry.ece.cmu.edu (David Hairston): > there's a no-brainer which has worked its way into my code (C example): > #define goodHand(x) ((x) && *(x)) > > which gets used for: > > realHandle = GetResource(type, index); > if (!goodHand(realHandle)) > .... Your no-brainer misses two potential problems: - if I call it with, say, "goodHand (myH++)" (or any other expression with side-effects) things get ugly (and VERY hard to debug!). - there is a distinction between handle==NULL and *handle==NULL for resources: a NULL handle either doesn't exist or hasn't been initialized, whereas a non-null resource handle which dereferences to a NULL indicates a purged resource -- call LoadResource to pull the data in. =Ned Horvath= -- =Ned Horvath= ehorvath@attmail.com
kaufman@neon.Stanford.EDU (Marc T. Kaufman) (05/08/91)
In article <1991May8.031012.1845@cbnewsk.att.com> ech@cbnewsk.att.com (ned.horvath) writes: >From article <12946@pt.cs.cmu.edu>, by hairston@henry.ece.cmu.edu (David Hairston): -> there's a no-brainer which has worked its way into my code (C example): -> #define goodHand(x) ((x) && *(x)) >- there is a distinction between handle==NULL and *handle==NULL for >resources: a NULL handle either doesn't exist or hasn't been initialized, >whereas a non-null resource handle which dereferences to a NULL indicates >a purged resource -- call LoadResource to pull the data in. And just to make it worse, *handle won't be NULL for a purged resource, but StripAddress(*handle) will be. The purge and resource bits are still on (at least in 24 bit memory models). Finally: a use for StripAddress. Marc Kaufman (kaufman@Neon.stanford.edu)
neeri@iis.ethz.ch (Matthias Ulrich Neeracher) (05/08/91)
In article <1991May8.055136.27101@neon.Stanford.EDU>, kaufman@neon.Stanford.EDU (Marc T. Kaufman) writes: >And just to make it worse, *handle won't be NULL for a purged resource, >but StripAddress(*handle) will be. The purge and resource bits are still >on (at least in 24 bit memory models). Are you sure about this ? I'm 99% sure that the purge bit is not set for purged handles. I don't know about the resource bit, but having seen that the purge bit gets cleared for purged handles (I think I have seen it !), I believe that all bits are cleared. Better check this out yourself, though. Matthias -- Matthias Neeracher neeri@iis.ethz.ch "These days, though, you have to be pretty technical before you can even aspire to crudeness." -- William Gibson, _Johnny Mnemonic_
REEKES@applelink.apple.com (Jim Reekes) (05/09/91)
In article <12946@pt.cs.cmu.edu>, hairston@henry.ece.cmu.edu (David Hairston) writes: > there's a no-brainer which has worked its way into my code (C example): > > #define goodHand(x) ((x) && *(x)) > > which gets used for: > > realHandle = GetResource(type, index); > if (!goodHand(realHandle)) > .... > > as well as for: > fooPointer = NewWindow(...); > if (!goodHand(&fooPointer)) A problem with goodHand above is that if the GetResource fails, then you may end up dereferencing a nil address. It will happen with Pascal's AND expression, but not with MPW Pascal's &. It all depends on the language's implementation. It's safe to just check on the handle being returned to be nil. Besides, calling GetResource will never return a handle that is purged, unless you set ResLoad to false and the resource isn't in memory. BUT... if you set ResLoad to false (which is a valid thing to do) then goodHand above will always report an error! I have to correct myself in my original response. > Another gottcha is to check ResError after calling HGetState. > Otherwise the result is trash, not handle state information so > don't call HSetState with it later. I meant to say always check _MemError_ after calling HGetState. Jim Reekes E.O., Macintosh Toolbox Engineering
pratt@csn.org (Jonathan Pratt) (05/09/91)
In article <13404@goofy.Apple.COM> REEKES@applelink.apple.com (Jim Reekes) writes: > >I meant to say always check _MemError_ after calling HGetState. > Assuming your program is already debugged, when is this going to give you anything other than noErr? IM IV doesn't document what result codes are possible, but how can you have problems if you call HGetState with a valid handle? Jonathan -- /* Jonathan Pratt Internet: pratt@boulder.colorado.edu * * UCHSC, Box A034 uucp: ..!ncar!boulder!pratt * * 4200 E. Ninth Ave. * * Denver, CO 80262 Phone: (303) 270-7801 */
pratt@csn.org (Jonathan Pratt) (05/09/91)
In article <1991May8.055136.27101@neon.Stanford.EDU> kaufman@neon.Stanford.EDU (Marc T. Kaufman) writes: >In article <1991May8.031012.1845@cbnewsk.att.com> ech@cbnewsk.att.com (ned.horvath) writes: >>From article <12946@pt.cs.cmu.edu>, by hairston@henry.ece.cmu.edu (David Hairston): > >-> there's a no-brainer which has worked its way into my code (C example): > >-> #define goodHand(x) ((x) && *(x)) > > >And just to make it worse, *handle won't be NULL for a purged resource, >but StripAddress(*handle) will be. The purge and resource bits are still >on (at least in 24 bit memory models). > Come on. Programming the Mac is enough work without this kind of dis- information. Next time get a reference. From Inside Mac: Before attempting to access any purgeable block, you must check its handle to make sure the block is still allocated. If the handle is empty (that is, h^ = NIL, where h is the handle), then the block has been purged; ... Last I heard, NIL still means zero. :-) Jonathan -- /* Jonathan Pratt Internet: pratt@boulder.colorado.edu * * UCHSC, Box A034 uucp: ..!ncar!boulder!pratt * * 4200 E. Ninth Ave. * * Denver, CO 80262 Phone: (303) 270-7801 */
d88-jwa@byse.nada.kth.se (Jon W{tte) (05/09/91)
In article <13404@goofy.Apple.COM> REEKES@applelink.apple.com (Jim Reekes) writes: > #define goodHand(x) ((x) && *(x)) A problem with goodHand above is that if the GetResource fails, then you may end up dereferencing a nil address. It will happen with Pascal's AND expression, but not with MPW Pascal's &. It all depends on the language's implementation. It's safe to just check on the handle Well, the example was in C, and C structly specifies lazy evaluation of logical expressions (like &&) unless you set ResLoad to false and the resource isn't in memory. BUT... if you set ResLoad to false (which is a valid thing to do) then goodHand above will always report an error! If you call SetResLoad(false) you probably know what you do, it's not a call to call lightly (and certain portions of the OS & toolbox will fail with SetResLoad(false)) -- Jon W{tte h+@nada.kth.se - Power !
time@ice.com (Tim Endres) (05/10/91)
In article <1991May9.040511.26710@colorado.edu>, pratt@csn.org (Jonathan Pratt) writes: > >And just to make it worse, *handle won't be NULL for a purged resource, > >but StripAddress(*handle) will be. The purge and resource bits are still > >on (at least in 24 bit memory models). > > > Come on. Programming the Mac is enough work without this kind of dis- > information. Next time get a reference. From Inside Mac: > > Before attempting to access any purgeable block, you must > check its handle to make sure the block is still allocated. > If the handle is empty (that is, h^ = NIL, where h is the > handle), then the block has been purged; ... > > Last I heard, NIL still means zero. :-) Actually, the flags for a handle are stored in the *handle*'s address. Thus, the dereference (* handle) should contain a "pure" address. Thus, the StripAddress() should only be required on the handle and *not* on the handle's dereferenced pointer. tim. ------------------------------------------------------------- Tim Endres | time@ice.com ICE Engineering | uupsi!ice.com!time 8840 Main Street | Voice FAX Whitmore Lake MI. 48189 | (313) 449 8288 (313) 449 9208
wysocki@husc9.harvard.edu (Christopher Wysocki) (05/11/91)
In article <1CE00001.falep4@tbomb.ice.com> time@ice.com writes: >Actually, the flags for a handle are stored in the *handle*'s address. >Thus, the dereference (* handle) should contain a "pure" address. >Thus, the StripAddress() should only be required on the handle and >*not* on the handle's dereferenced pointer. This is not the case. With 24-bit addressing, the flag bits for a relocatable block are stored in the high byte of the block's master pointer (IM II-25). In light of this, you definitely *should* call StripAddress for a master pointer if, for instance, you're comparing the addresses of master pointers. Chris Wysocki wysocki@husc9.harvard.edu
Greg@AppleLink.Apple.Com (Greg Marriott) (05/11/91)
In article <1CE00001.falep4@tbomb.ice.com>, time@ice.com (Tim Endres) writes: > Actually, the flags for a handle are stored in the *handle*'s address. > Thus, the dereference (* handle) should contain a "pure" address. > Thus, the StripAddress() should only be required on the handle and > *not* on the handle's dereferenced pointer. Sorry, this is dead wrong. The memory manager stores the flags in the high byte of the master pointer. So, (* handle) will contain a "dirty" address if you're running in 24-bit mode. In 32-bit mode, the flags are stored elsewhere. Greg Marriott Blue Meanie Apple Computer, Inc.