TweetFollow Us on Twitter

March 93 - MACINTOSH DEBUGGING: THE BELLY OF THE BEAST REVISITED

MACINTOSH DEBUGGING: THE BELLY OF THE BEAST REVISITED

FRED HUXHAM AND GREG MARRIOTT

ADAPTED FROM THEIR TALK AT THE WWDC BY DAVE JOHNSON

[IMAGE Huxham_Marriott_rev1.GIF]

This is a supplement to the article "Macintosh Debugging: A Weird Journey Into the Belly of the Beast" in Issue 8 of develop. It presents a few debugging tools that were discussed at Apple's Worldwide Developers Conference in May 1992. Like those discussed in the previous article, these tools are designed to help you force the nasty, subtle bugs in your code to show their hideous little faces immediately, rather than lying in wait and biting you when you least expect it.

People often ask us, "How can I be a totally awesome, godlike debugging stud [or studette] like you?" Unfortunately, the big truth from the Issue 8 debugging article is just as true now as it was then: debugging is hard. That's just the way it is. The only way to get better at it is to practice. Now that we've got that straight and before we get into describing the new debugging tools, here are three pearls of wisdom to guide you in your practice.

First of all, it helps to know a lot about the operating system. The better sense you have of how the Macintosh works, the better off you'll be trying to track down a nasty bug. Dare to delve into the bowels of the OS. Read and rereadInside Macintosh; take it with you to bed, to the bathroom, out to dinner, and on dates. (You might want to invest in a sturdy wheelbarrow, especially with the new Inside Macintosh volumes proliferating like rabbits.) For that matter, read every Macintosh programming book ever written (especially those listed at the end of this article) and every Technical Note, Snippet, piece of Sample Code, and issue ofdevelop, as well as every word on the AppleLink Discussion boards. Also, spend lots of time in debuggers, watching the system do its thing. If you're not dreaming in hex, you're not spending enough time in MacsBug.

Second, get slammed a lot. The people who are the best at debugging are usually the ones who've had to track down the most bugs and therefore have an encyclopedic knowledge of them. If you have a really nasty bug in your code that crashes the machine on a seemingly random basis and takes you three days to find and squash, then by jove you'll remember that bug the next time you see it. Simply put, the more bugs you find, the better you'll be at finding bugs.

Last, use good tools, and use them all. Reread the Issue 8 article. Turn on those tools and stress your code. Bend, fold, staple, and mutilate it. Show no mercy.

These things will help you on your way to becoming a primo bug stomper, but debugging is like any complex skill in that it can't really be taught past a certain point. You simply have to do it a lot, andover time you'll get better. Tools and techniques such as the ones presented here can help enormously, especially by forcing hidden bugs to the surface, but they can never do the whole job for you.

This time there are only four new tools to talk about -- Double Trouble, Dispose Resource, Blat, and Smart Friends -- so this article is much shorter than the last one. The tools are available on theDeveloper CD Seriesdisc, as well as on AppleLink and elsewhere. We're doing this backward from the last time: first we'll present a buggy code sample, then we'll talk about the tool that would find the bug.

DOUBLE TROUBLE

Can you find the bug in this code sample?
myHandle = NewHandle(100);
if (myHandle) {
    AddResource(myHandle, 'dumb', 10, "\p");
    if (resError()) HandleTheError();
    CloseResFile(outputFileRef);
    DisposeHandle(myHandle);
}

OK, time's up. This one's not too hard. The problem is that during CloseResFile the Resource Manager disposes of all the resources in memory. The DisposeHandle call afterward is unnecessary and is actually potentially disastrous. Normally you'll just get an error and DisposeHandle will do nothing, but occasionally the data structures in the Memory Manager will conspire to really screw you.

Here's how: Master pointers are allocated in clumps called master pointer blocks, which are nonrelocatable blocks in your application's heap. The master pointers that are currently free for use are kept in a linked list by the Memory Manager. The list is LIFO, like a stack: when you allocate a new handle, the Memory Manager uses the first master pointer in the free list, and when you dispose of a handle the freed master pointer is returned to the beginning of the list.

Now the plot thickens. If the first master pointer in the free list also happens to be the first master pointer in its master pointer block (so that the master pointer and the master pointer block have the same address) and then you dispose of a handle twice by mistake,very bad thingswill happen. On the first dispose, everything is fine: the Memory Manager frees the block the master pointer points to and returns the master pointer to the start of the free list. At this time, the master pointerstill points to a valid block of memory, but now it's the master pointer block itself! So on the second, unintentional dispose, when the Memory Manager dutifully frees the block for reuse, you're set up for disaster. Subsequent memory use will likely result in writing over many master pointers, which will of course trash you one way or another.

Figure 1 illustrates this scenario. On the left is the top part of a master pointer block that resides in the heap at address 80. The heap's free list is a standard linked list (each entry contains the next entry's address) beginning at hFstFree. Note that the first entry in the heap's free list is also the first master pointer in the block. This is the first step to trouble.

[IMAGE Huxham_Marriott_rev2.GIF]

Figure 1 How Disposing of the Same Handle Twice Can Spell Disaster

Now we call DisposeHandle on the master pointer at 81. DisposeHandle looks at the block pointed to by the master pointer (in this case the block at 144, not shown), determines that it is indeed a valid block, marks it as free for reuse, and adds the newly freed master pointer to the front of the free list. So far so good. Now the master pointer block looks like the one on the right in the figure.

Then we call DisposeHandle on 81 again by mistake. DisposeHandle looks at the block pointed to by the master pointer (now it's the block at 80, our master pointer block!), determines that it is indeed a valid block (uh oh), marks it as free for reuse (yikes!), and adds the newly freed master pointer to the front of the free list -- and the heap is now hosed for good. This Memory Manager bug is subtle and rare, but oh so nasty.

Even if you're lucky enough to avoid this particular sequence of events, a double disposal is definitely a bug. Double Trouble is a system extension that watches calls to DisposeHandle to make sure it's not being called on something in the free list. If it is, Double Trouble drops into the debugger with a suitable warning.

We'll be the first to admit that Double Trouble is far from perfect. It infers the existence of heap zones by watching InitZone and then trying to figure out when a heap isn't a heap anymore. The possibility exists that it will guess wrong and cause a bus error when trying to walk a free list that's no longer a free list. Furthermore, in some cases Double Trouble can noticeably slow down parts of the system. (After playing a long QuickTime movie, for instance, the machine may freeze for almost a minute.)

But despite Double Trouble's shortcomings, we do still recommend running it all the time. Just try to remember that it's running so you don't chase your tail trying to find the cause of occasional mysterious slowdowns.

DISPOSE RESOURCE

Here's the code. What's the bug?
myPicture = GetPicture(kPicID);
if (myPicture) {
    DrawPicture(myPicture, &myRect);
    DisposeHandle(myPicture);
}

That's right, you should never call DisposeHandle on a resource handle. If you do, the Memory Manager will free it just fine, but the Resource Manager has another reference to it, stored in the resource map, that will be left dangling. Later on, since the Resource Manager doesn't know the handle was disposed of, it may try some manipulation with the handle. The results may not crash you immediately, or at all -- it depends on what the operation is and what's in the handle -- but they're certainly not what was intended. Instead of DisposeHandle, you should always call ReleaseResource on resource handles. ReleaseResource will properly dispose of the handleandwill update the resource map. (Note that KillPicture won't do the right thing here either; it's intended for pictures created via OpenPicture, not for PICT resources.)

Dispose Resource is another extension a lot like Double Trouble. It also watches DisposeHandle calls, this time looking to see if the handle being disposed of is a resource handle. If so, you'll drop into the debugger with a suitable warning.

Dispose Resource has one idiosyncrasy you should know about: it's been known to indicate "false positives." Some parts of the system (we haven't been able to track down which ones yet) seem to save a resource handle's state, detach the resource, and then restore the state of the handle (restoring the resource bit!). Use Dispose Resource. It will ensure that you don't make the same mistake.

BLAT

This time the code's in assembler:
; Offset the rect by 128 pixels in each direction.
PEA         theRect(A6)
MOVE.W      $0080, -(SP)
MOVE.W      $0080, -(SP)
_OffsetRect

If you have "iron man" syndrome and insist on programming in assembly language, this can happen to you. We forgot to type a # in front of each $0080. As a result, instead of moving the number $0080 (128) onto the stack twice in preparation for the OffsetRect call, we're moving the contents of memory location $0080. Often this kind of bug is immediately obvious, but not always. If you're moving a Boolean, for instance, you have a fifty-fifty chance of getting the right value, even though you're getting it from some random spot in memory. It's those cases that will give you debugging headaches.

One easy (and recommended) way to avoid the problem in this example is to write in a higher-level language. But we realize that's not always possible, and besides, this is really a wholeclassof problems: reads and writes from places in memory you didn't intend. The best way to catch this wild memory reference kind of problem is, naturally, with memory protection, something that -- sadly -- the Macintosh normally lacks. In the last article we mentioned Jasik's implementation, but now there's something else you should know about. Bo3b Johnson has written a dcmd called Blat that uses the MMU to protect memory locations 0-255 from both reads and writes.

Blat has been tested and works well on the Macintosh IIfx, IIx, and SE/30. Because its operation is so hardware dependent, it's hard to predict whether it will work on a given machine. Some basic guidelines are that it requires an MMU and won't work with 68040 machines or with most configurations of machines with the IIci ROM (IIci, IIsi, LC). For further details, see the release notes and the source code, thoughtfully provided by Bo3b along with the dcmd itself.

SMART FRIENDS

This bug is subtle, so pay close attention:
#pragma parameter __d0 GetA0
Ptr GetA0(void) = {0x2008};  // MOVE.l A0,D0

void MyCompletionRoutine()
{
    long        saveA5;
    HooHahPtr   myHooHah;
    
    myHooHah = (HooHahPtr)GetA0();
    saveA5 = SetA5(myHooHah->myA5);
    gSomething[0].flag = true; // Set a flag in a global array. 
    SetA5(saveA5);
}

This code really tries hard to do everything right. As the name implies, it's a completion routine, so it could be called at interrupt time. First a pointer to the data is retrieved from A0, and then A5 is set to a previously saved value, thus allowing the routine to access its global variables. Once A5 is set up, the global reference can be made safely. Finally, A5 is restored to its previous value to clean up. Sounds great, right? The only problem is, it doesn't work.

Here's why: the MPW C compiler will actually set up the global referencebeforethe SetA5 call, so accessing the global accesses some unknown part of memory. This is legal compiler optimization behavior! If GetA0 and SetA5 were functions or traps, the bug would disappear, but since they're declared inline the compiler doesn't feel compelled to delay the evaluation of the global array reference. The solution is to set up A5, then call a different routine that does the global reference.

Now in this case, how do you think we -- the debugging gods -- figured out the bug? We tried the first few things we could think of; but then when we weren't making headway after a few probes, we didn't just sit there and suffer in silence, banging our heads against the proverbial wall. We called in some Smart Friends! The veil of illusion was torn from our eyes, and we were shown the heart of the truth (in other words, one of them had seen this bug before). The point is that in debugging, two (or more) heads are far, far better than one. Bugs are not like germs: when you share them, everyone benefits. Maybe your very own Smart Friends have had a similar bug before, so they'll recognize immediately what's going on. Or maybe they'll think of something different to try. At the very least, they'll temporarily divert you from your frustration, maybe make you feel less stupid, and then you can all go out for pie together.

THAT'S IT!

Add these tools to your arsenal of bug sprays and foggers. Use them all and use them well, and you, your code, and your customers will be far better off.

FURTHER READING

Bedside books for the serious student of debugging:

  • How to Write Macintosh Software, 3rd ed., by Scott Knaster and Keith Rollin (Addison-Wesley, 1992).
  • Macintosh Programming Secrets, 2nd ed., by Scott Knaster and Keith Rollin (Addison-Wesley, 1992).
  • Debugging Macintosh Software with MacsBug by Konstantin Othmer and Jim Straus (Addison-Wesley, 1991).
  • MC68000 Family Programmer's Reference Manual (Motorola, Inc.).

FRED HUXHAM (AppleLink FRED) was born and raised in California. He used to be a tremendous athlete, know bazillions of babes, and go to wild parties in New York and California with people like Andy Warhol and Keith Haring. Now he's 15 pounds heavier, knows only one babe (his wife), and thinks a day spent sitting on his roof deck watching boats go through the Golden Gate is really exciting.*

GREG MARRIOTT (AppleLink GREG) is a SWM, 28, 6'0", 195 lbs., brown hair and eyes, sincere, hardworking, good sense of humor. Enjoys music, romantic walks, quiet evenings, and good books. Seeks nice woman for friendship and more. Send photo.*

In Bo3b's name, the "3" is silent. *

THANKS TO OUR TECHNICAL REVIEWERS Jim Reekes and Bryan Stearns*

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Backup and Sync 3.46 - File backup and s...
Backup and Sync (was Google Drive) is a place where you can create, share, collaborate, and keep all of your stuff. Whether you're working with a friend on a joint research project, planning a... Read more
iClock 5.5 - Customizable menu bar clock...
iClock replaces the old Apple's default menu bar clock with more features, customization and increases your productivity. Features: Have your Apple or Google calendar instantly available from the... Read more
Garmin Express 6.18.0.0 - Manage your Ga...
Garmin Express is your essential tool for managing your Garmin devices. Update maps, golf courses and device software. You can even register your device. Update maps Update software Register your... Read more
MarsEdit 4.3.5 - Quick and convenient bl...
MarsEdit is a blog editor for OS X that makes editing your blog like writing email, with spell-checking, drafts, multiple windows, and even AppleScript support. It works with with most blog services... Read more
Xcode 11.0 - Integrated development envi...
Xcode includes everything developers need to create great applications for Mac, iPhone, iPad, and Apple Watch. Xcode provides developers a unified workflow for user interface design, coding, testing... Read more
DaisyDisk 4.8 - $9.99
DaisyDisk allows you to visualize your disk usage and free up disk space by quickly finding and deleting big unused files. The program scans your disk and displays its content as a sector diagram... Read more
VMware Fusion 11.5.0 - Run Windows apps...
VMware Fusion and Fusion Pro - virtualization software for running Windows, Linux, and other systems on a Mac without rebooting. The latest version includes full support for Windows 10, macOS Mojave... Read more
Apple Configurator 2.10 - Configure and...
Apple Configurator makes it easy to deploy iPad, iPhone, iPod touch, and Apple TV devices in your school or business. Use Apple Configurator to quickly configure large numbers of devices connected to... Read more
Spotify 1.1.15.448. - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
MenuMeters 1.9.8 - CPU, memory, disk, an...
MenuMeters is a set of CPU, memory, disk, and network monitoring tools for Mac OS X. Although there are numerous other programs which do the same thing, none had quite the feature set I was looking... Read more

Latest Forum Discussions

See All

Marvel Strike Force is adding Agent Coul...
Marvel Strike Force, the popular squad-based RPG, is set to receive a bunch of new content over the next few weeks. [Read more] | Read more »
Lots of premium games are going free (so...
You may have seen over the past couple weeks a that a bunch of premium games have suddenly become free. This isn’t a mistake, nor is it some last hurrah before Apple Arcade hits, and it’s important to know that these games aren’t actually becoming... | Read more »
Yoozoo Games launches Saint Seiya Awaken...
If you’re into your anime, you’ve probably seen or heard of Saint Seiya. Based on a shonen manga by Masami Kurumada, the series was massively popular in the 1980s – especially in its native Japan. Since then, it’s grown into a franchise of all... | Read more »
Five Nights at Freddy's AR: Special...
Five Nights at Freddy's AR: Special Delivery is a terrifying new nightmare from developer Illumix. Last week, FNAF fans were sent into a frenzy by a short teaser for what we now know to be Special Delivery. Those in the comments were quick to... | Read more »
Rush Rally 3's new live events are...
Last week, Rush Rally 3 got updated with live events, and it’s one of the best things to happen to racing games on mobile. Prior to this update, the game already had multiplayer, but live events are more convenient in the sense that it’s somewhat... | Read more »
Why your free-to-play racer sucks
It’s been this way for a while now, but playing Hot Wheels Infinite Loop really highlights a big issue with free-to-play mobile racing games: They suck. It doesn’t matter if you’re trying going for realism, cart racing, or arcade nonsense, they’re... | Read more »
Steam Link Spotlight - The Banner Saga 3
Steam Link Spotlight is a new feature where we take a look at PC games that play exceptionally well using the Steam Link app. Our last entry talked about Terry Cavanaugh’s incredible Dicey Dungeons. Read about how it’s a great mobile experience... | Read more »
Combo Quest (Games)
Combo Quest 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Combo Quest is an epic, time tap role-playing adventure. In this unique masterpiece, you are a knight on a heroic quest to retrieve... | Read more »
Hero Emblems (Games)
Hero Emblems 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: ** 25% OFF for a limited time to celebrate the release ** ** Note for iPhone 6 user: If it doesn't run fullscreen on your device... | Read more »
Puzzle Blitz (Games)
Puzzle Blitz 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Puzzle Blitz is a frantic puzzle solving race against the clock! Solve as many puzzles as you can, before time runs out! You have... | Read more »

Price Scanner via MacPrices.net

11″ WiFi iPad Pros on sale today for up to $2...
Amazon has new 2018 Apple 11″ WiFi iPad Pros in stock today and on sale for up to $200 off Apple’s MSRP. These are the same iPad Pros sold by Apple in its retail and online stores. Be sure to select... Read more
Select 12″ iPad Pros on sale for $200 off App...
Amazon has select 2018 Apple 12″ iPad Pros in stock today and on sale for $200 off Apple’s MSRP. These are the same iPad Pros sold by Apple in its retail and online stores. Be sure to select Amazon... Read more
Get one of Apple’s new 2019 iPhone 11 models...
Boost Mobile is offering the new 2019 Apple iPhone 11, iPhone 11 Pro, and 11 Pro Max for $100 off MSRP. Their discount reduces the cost of an iPhone 11 to $599 for the 64GB models, $899 for the 64GB... Read more
13″ 1.4GHz Silver MacBook Pros on sale for $1...
B&H Photo has new 2019 13″ 1.4GHz 4-Core Touch Bar Silver MacBook Pros on sale for $100 off Apple’s MSRP. Overnight shipping is free to many addresses in the US. These are the same MacBook Pros... Read more
4-core and 6-core 2018 Mac minis available at...
Apple has Certified Refurbished 2018 Mac minis available on their online store for $120-$170 off the cost of new models. Each mini comes with a new outer case plus a standard Apple one-year warranty... Read more
$250 prepaid Visa card with any Apple iPhone,...
Xfinity Mobile will include a free $250 prepaid Visa card with the purchase of any new iPhone, new line activation, and transfer of phone number to Xfinity Mobile. Offer is valid through October 27,... Read more
Sprint is offering the 64GB Apple iPhone 11 P...
Sprint has the new 64GB iPhone 11 Pro available for $12.50 per month for new customers with an eligible trade-in in of iPhone 7 or newer. That’s down from their standard monthly lease of $41.67. The... Read more
Final week: Apple’s 2019 Back to School Promo...
Purchase a new Mac using Apple’s Education discount, and take up to $400 off MSRP. All teachers, students, and staff of any educational institution with a .edu email address qualify for the discount... Read more
Save $30 on Apple’s AirPods at these reseller...
Amazon is offering discounts on new 2019 Apple AirPods ranging up to $30 off MSRP as part of their Labor Day sale. Shipping is free: – AirPods with Charging Case: $144.95 $15 off MSRP – AirPods with... Read more
Preorder your Apple Watch Series 5 today at A...
Amazon has Apple Watch Series 5 GPS models available for preorder and on sale today for $15 off Apple’s MSRP. Shipping is free and starts on September 20th: – 40mm Apple Watch Series 5 GPS: $384.99 $... Read more

Jobs Board

Systems Analyst ( *Apple* & Android) (Jo...
Systems Analyst ( Apple & Android) (Job ID: 572513) + 11751 Meadowville Ln, Chester, VA 23836, USA + Full-time Company Description Computer Consultants International, Read more
*Apple* Mobile App Developer - eiWorkflow So...
…eiWorkflow Solutions, LLC is currently looking for a consultant for the following role. Apple Mobile App Developer Tasks the role will be performing: ? Mobile App Read more
Essbase Developer - *Apple* - Theorem, LLC...
Job Summary Apple is seeking an experienced, detail-minded Essbase developer to join our worldwide business development and strategy team. If you are someone who Read more
Student Employment (Blue *Apple* Cafe) Spri...
Student Employment (Blue Apple Cafe) Spring 2019 Penn State University Campus/Location: Penn State Brandywine Campus City: Media, PA Date Announced: 12/20/2018 Date Read more
Best Buy *Apple* Computing Master - Best Bu...
**732093BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Location Number:** 001441-Beaumont-Store **Job Description:** The Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.