Playing with Blocks
Volume Number: 8
Issue Number: 7
Column Tag: Debugging
Memory manager structures - a software autopsy of your application's
death!
By Brooks Bell, Bradenton, Florida
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
Let’s set the ‘Way Back’ machine for 1985. Programmers of the day complained
heavily of the information that Apple was keeping to itself. Inside Macintosh just did not
provide enough details.
The chapter on the Memory Manager, for example, was fuzzy on the meaning of
certain fields in the Zone header. SparePtr, allocPtr even the ever-popular flags
field were defined only as ‘used internally’. Even worse, fields such as cntRel, maxRel,
and cntHandles were described as ‘not used’, when any debugger showed that they
clearly contained valid data.
Of course, we have all by now learned that these things are hidden from
programmers because they are fair game for change. What works for a 512K “Fat”
Mac isn’t necessarily applicable to a Quadra with 64MB of RAM. We have grown
accustomed to the trade off: Apple shields us from some OS details in exchange for
blessed future hardware compatibility.
That is why it is something of a surprise to turn a few pages further in IM II and
discover a very detailed description of the old 24 bit memory manager block structure.
In retrospect, this knowledge led directly to the problems of 32 bit uncleanliness. Here
is how to set the Master Pointer ‘lock’ bit and bypass the HLock trap overhead.
Lo3Bytes is described - who needs StripAddress? Everything that you need to make a
32 bit dirty application is right here in black and white.
With the 32 bit memory manager and Inside Macintosh VI, having learned from
their mistakes, Apple decided not to publish the Memory Manager block structures.
Well written applications will use HGetState, HLock, etc There is no need to risk
compatibility by accessing these structures directly.
However, when you are in the middle of debugging some code errors can crop up
that cause an invalid heap. Because the Mac ROMs do not check parameters for errors,
it is easy to pass a trap a bad value and have it write garbage all over the heap. It is also
easy to move data into a disposed handle, store data beyond the bounds of an array,
maybe even call BlockMove directly and blast data all over creation. Lacking
sophisticated memory protection, the Macintosh heap is easily destroyed.
Perhaps the worst aspect of such damage is that fatal errors may not appear for
some time. When they do show up in the form of the friendly ‘illegal instruction’,
‘Stack has collided with the heap’, ‘Bus Error’ or whatever the program may have
crawled, bleeding, thousands of instructions away from the offending line of code.
It is at this point that the knowledge of memory manger structures can often be
put to good use. If you are lucky enough to still have a low level debugger functioning,
knowing the structure of the heap can provide vital information in “cracking the case”.
Think of it as a software autopsy to determine the cause of your application’s death.
Healthy, Happy Heaps
At the highest level, the heap is made up of three basic components. There is one
Zone Header, one Zone Trailer, and in between the two lie any number of blocks. The
blocks occupy all the space in the heap and are divided into three categories: free,
non-relocatable, and relocatable. This article will focus on the internal structure of
these blocks.
Figure 1
With the recent addition of the new Inside Macintosh Memory volume Apple has
decided to publish the 32 bit heap structures they left out of IM VI. Note that using
these structures in a program guarantees incompatibility when Apple changes the
memory manager. Precisely when that will happen is anyone’s guess, but with PowerPC
looming on the horizon I’d imagine this information has a useful shelf life of less than
two years.
Both 24 bit and 32 bit memory manager blocks have the same general structure.
Blocks always begin with a Block Header, followed by any amount of logical data. A
variable sized padding field may be tacked onto the end. The size of the entire structure
is called the block’s physical size. Applications never deal with this size. The size of the
variable length logical data field is called the logical size. It is this logical size that is