home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!olivea!pagesat!netsys!agate!stanford.edu!eos!data.nas.nasa.gov!taligent!kip-50.taligent.com!user
- From: keith@taligent.com (Keith Rollin)
- Newsgroups: comp.sys.mac.programmer
- Subject: Re: Verifying valid handles, how to?
- Message-ID: <keith-220193155445@kip-50.taligent.com>
- Date: 23 Jan 93 00:04:58 GMT
- References: <1993Jan22.015520.1@fnalo.fnal.gov> <NEERI.93Jan22190934@iis.ethz.ch>
- Sender: usenet@taligent.com (More Bytes Than You Can Read)
- Followup-To: comp.sys.mac.programmer
- Organization: Taligent
- Lines: 133
-
- In article <NEERI.93Jan22190934@iis.ethz.ch>, neeri@iis.ethz.ch (Matthias
- Neeracher) wrote:
- >
- > In article <1993Jan22.015520.1@fnalo.fnal.gov>, gwatts@fnalo.fnal.gov writes:
- > > At any rate, I was thinking. I've got only indirect objects in my project.
- > > This means every object is a handle, right? Well, why not, in the debug
- > > version of the message dispatcher (oopDebug library) put a little code that
- > > will check the object is infact allocated as a handle?
- > > I checked out the routine in msg.c (in the oops Libraries folder), and
- > > the handle is stored in register a1. I don't know, however, how to check
- > > if it is a valid handle without causing an error (bus or otherwise) of
- > > somesort. Especially if it is a random number! Anyone know? Is there
- > > some memory manager routine, given a suspected handle, will tell me this?
- >
- > Here you go. This code is not guaranteed to work 100% of the time, but I doubt
- > you will get it to produce an address error for any normal memory setup (One
- > exception I can think of are macs with a memory upgrade that makes the ROM
- > appear in the middle of the application heap).
- >
- > /* Heuristic to determine whether a given address is a Handle */
- > /* Based on the articles of Lloyd Lim and Matthew T Russotto in the UMPG */
- > /* This code may be redistributed without any restrictions */
- >
- > Boolean RealHandle(void * addr)
- > {
- > THz sysZone;
- > THz applZone;
- > THz heapZone;
- >
- > addr = StripAddress(addr);
- > if (addr && !((long) addr & 1)) {
- > sysZone = SystemZone();
- > applZone = ApplicZone();
- > if (addr >= (Ptr) &sysZone->heapData &&
- > addr < (Ptr) sysZone->bkLim ||
- > addr >= (Ptr) &applZone->heapData &&
- > addr < (Ptr) applZone->bkLim
- > )
- > if (*(long *)addr && !(*(long *)addr & 1)) {
- > heapZone = HandleZone(addr);
- > if (!MemError())
- > if (heapZone == sysZone || heapZone == applZone)
- > return true;
- > }
- > }
- >
- > return false;
- > }
-
- I think that the above routine tries to validate any value that you might
- have lying around. However, if you have a value that you know at one time
- was a handle, you might want to check to see if it's on the free chain or
- not (this code is from MacApp):
-
- Boolean IsFreeHandle(Handle aHandle)
- {
- THz applZone = ApplicZone();
- Handle currHandle = (Handle) applZone->hFstFree;
-
- while (currHandle != NULL)
- {
- if (currHandle == aHandle)
- return TRUE;
- currHandle = (Handle) * currHandle;
- }
- return FALSE;
- }
-
- If course, nothing will help you if the master pointer has been
- re-allocated. Your old handle will now be pointing to a new, perfectly
- valid block of memory. I think the only thing you can do at that point is
- check the handle size against sizeof(TYourClass).
-
- Greg Marriott (who was seen the other night at the Red Pepper with Cindy
- Jasper) wrote an INIT that tries to detect double-dispose bugs. It's on
- Apple's Developer CD and probably other places. Here are the release notes
- for your reading pleasure:
-
- ;
- ; DoubleTrouble - by Greg Marriott
- ;
- ; ) 1992, Apple Computer, Inc.
- ;
- ; DoubleTrouble is a debugging utility made to catch a common programming
- error:
- ; freeing a handle that has already been freed. (I call these errors
- Rdouble
- ; dispose bugsSI)
- ;
- ; When _DisposeHandle is called on a handle, the memory manager adds the
- handle
- ; to its Rfree list,S a linked list of handles available for the allocator
- to use.
- ; Calling _DisposeHandle on that handle again is usually benign. The
- memory
- ; manager dereferences the handle, pointing to the next handle in the free
- list.
- ; If the the dereferenced handle points to the first handle in a master
- pointer block,
- ; however, the handle appears valid because it points to a real block. The
- memory
- ; manager fails to realize the block is NOT a relocatable block (all master
- pointer
- ; blocks are nonrelocatable), and marks it free (yikes!). The freed master
- pointer
- ; block is then used in a future allocation (usually very soon after being
- freed).
- ; This mangles several master pointers and the free list. Crashes soon
- follow.
- ;
- ; This kind of bug is very hard to track down, and usually difficult to
- reproduce,
- ; because master pointer blocks contain 64 handles (by default, some
- programs
- ; change this behavior). So, this situation only comes up about 1/64th of
- the
- ; time. When it happens, though, the results are inevitably catastrophic.
- ;
- ; DoubleTrouble compares each handle being disposed to every handle in the
- free list of
- ; the zone containing the handle. If the handle is already in the free
- list, DoubleTrouble
- ; breaks into the debugger with a message indicating whatUs going on.
- Continuing execution
- ; will stuff memWZErr (WhichZone failed, -111) into MemErr and d0 and
- return to the caller
- ; (and NOT call through to _DisposeHandle).
- ;
-
- -----
- Keith Rollin
- Phantom Programmer
- Taligent, Inc.
-