[comp.sys.mac.programmer] Identifying real handles

lim@iris.ucdavis.edu (Lloyd Lim) (06/04/90)

This is perhaps not the best thing to do on a Mac but I need to be able to
tell if some arbitrary long is a real handle in the System heap or the current
app heap.  I want to keep it relatively clean so I don't want to go looking
through the heap's internal structures.  Currently, I use the following code:

Boolean ValidHandle(address)

register long address;

{
   register Boolean  valid;
   register THz      heapZone;
   
   valid = FALSE;
   if (address && !(address & 1)) {
      heapZone = HandleZone(address);
      if (!MemError() && (heapZone == SystemZone() ||
                          heapZone == ApplicZone())) {
         valid = TRUE;
      }
   }
   return(valid);
}

The problem is that this routine can get passed any arbitrary long and that
some values seem to cause a bus error with HandleZone.  I say "seem" because
I haven't been able to find a value which causes a bus error in a test program
but bus errors do occur in the real situation if enough values are examined.
The real situation is practically unobservable.

Any ideas on a better way?  If you try doing extra checking before calling
HandleZone, you'll get bus errors right away when you do (*(Ptr) address).
If there is a solution that isn't right 100% of the time but doesn't cause
bus errors, that would also be ok.

+++
Lloyd Lim     Internet: lim@iris.ucdavis.edu (128.120.57.20)
              Compuserve: 72647,660
              US Mail: 146 Lysle Leach Hall, U.C. Davis, Davis, CA 95616

russotto@eng.umd.edu (Matthew T. Russotto) (06/05/90)

In article <7426@ucdavis.ucdavis.edu> lim@iris.ucdavis.edu (Lloyd Lim) writes:
>This is perhaps not the best thing to do on a Mac but I need to be able to
>tell if some arbitrary long is a real handle in the System heap or the current
>app heap.  I want to keep it relatively clean so I don't want to go looking
>through the heap's internal structures.  Currently, I use the following code:
>
>Boolean ValidHandle(address)
>
>register long address;
>
>{
>   register Boolean  valid;
>   register THz      heapZone;
>   
>   valid = FALSE;
>   if (address && !(address & 1)) {
>      heapZone = HandleZone(address);
>      if (!MemError() && (heapZone == SystemZone() ||
>                          heapZone == ApplicZone())) {
>         valid = TRUE;
>      }
>   }
>   return(valid);
>}
>
>The problem is that this routine can get passed any arbitrary long and that
>some values seem to cause a bus error with HandleZone.  I say "seem" because
>I haven't been able to find a value which causes a bus error in a test program
>but bus errors do occur in the real situation if enough values are examined.
>The real situation is practically unobservable.

Check to see if the handle itself is below BufPtr or MemTop or
whatever variable you feel is appropriate.  If it's below that, there should
never be a bus error.  Then do validity checks on *address, and check to see
if IT is below BufPtr or MemTop. Then call HandleZone.


--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?

odawa@well.sf.ca.us (Michael Odawa) (06/07/90)

In article <7426@ucdavis.ucdavis.edu> lim@iris.ucdavis.edu (Lloyd Lim) writes:

> ...I need to be able to tell if some arbitrary long is a real handle in 
> the System heap or the current app heap.  I want to keep it relatively clean
> so I don't want to go looking through the heap's internal structures...The
> problem is that this routine can get passed any arbitrary long and that some
> values seem to cause a bus error with HandleZone....Any ideas on a better
> way?

You have to make a range check against the high end of your memory.  Here's
something you might add to your code:

{
   register Boolean  valid;
   register THz      heapZone;
   
   valid = FALSE;
   if (address && !(address & 1)) {
	  if (address < long(**ApplicZone.BkLim)) {	/*****	Add this line	*****/
	      heapZone = HandleZone(address);
    	  if (!MemError() && (heapZone == SystemZone() ||
        	                  heapZone == ApplicZone())) {
        	 valid = TRUE;
      }
   }
   return(valid);
}

A different check (which I do in my version of ValidHandle) might be to
determine whether the tag byte on the block header (the first of the eight
bytes which preceed the address) contained 0x8x, as documented in IM II-24:

	if (address < long(**ApplicZone.BkLim))
		if ((*(ptr)(address - 8) & 0x80) != 0)
			valid = TRUE;

Of course, we have not even begun to discuss problems with 24-bit vs 32-bit
addressing schemes.  So perhaps we ought to preceed our code by

	address = (long)StripAddress((ptr)address);

-----

Michael Odawa
Simple Software
odawa@well.sf.ca.us

lsr@Apple.COM (Larry Rosenstein) (06/08/90)

In article <18379@well.sf.ca.us> odawa@well.sf.ca.us (Michael Odawa) 
writes:

> A different check (which I do in my version of ValidHandle) might be to
> determine whether the tag byte on the block header (the first of the 
eight
> bytes which preceed the address) contained 0x8x, as documented in IM 
II-24:

Unfortunately, this isn't 32-bit clean.  The block headers in the 32-bit 
Memory Manager seem to be 12 bytes long (instead of 8).  (I say "seem to 
be" since I was poking around without documentation.)

In addition to the other tests that were mentioned, you might try testing 
whether RecoverHandle(addresss^)=address.  (This is part of MacApp's 
IsHandle check.)  If you do this, you have to be careful because 
RecoverHandle only works if the current heap zone is the same as the 
handle's.  You also have to check for an empty handle (one whose master 
pointer is NIL).

Larry Rosenstein, Apple Computer, Inc.
Object Specialist

Internet: lsr@Apple.com   UUCP: {nsc, sun}!apple!lsr
AppleLink: Rosenstein1