NOTE: This Technical Note has been
retired. Please see the Technical Notes
page for current documentation.|
GraphicsBug is a quirky utility that provides a Macsbug-like view of Quickdraw GX applications. Although it may look like an application itself, don't let the menus and windows fool you; GraphicsBug is best used sparingly as a command-line debugger, not a cut-and-paste text program. GraphicsBug is aptly named: it's full of bugs. Still, it can be an indispensable tool when GX isn't working the way you expect.
GraphicsBug in Action
One simple task GraphicsBug performs well is confirming that your GX Graphics code does what you think it does. After you've executed the code, you can determine:
Starting up GraphicsBug
GraphicsBug for QuickDraw GX 1.1.3 is available on the Apple web site.
When GraphicsBug launches, it opens an untitled window, as shown in
GraphicsBug appears to be an ordinary application with traditional menus (1 in Figure 1). (Avoid these.) The real action happens in the Command line (2 in Figure 1) -- most commands are entered here. Always start by switching to your GX application's heap. You can choose it in the Heap menu (3 in Figure 1), or by using the Heap eXchange (hx) command.
GraphicsBug commands can be extremely terse. For instance, the following selects only the GX application that begins with the letter 'm':
The content pane of the window (4 in Figure 1) is used for GraphicsBug's response to commands.
You can find the address of your application with the LC command, which stands for List Clients:
Set the heap to the address under the ApHeap column:
There are only a few commands you'll need to debug most graphics and printing applications. The remaining commands are mostly useful for GX engineers and those curious about the inner workings of GX. Use any command with care; it's best to have work in progress in other applications saved, and to have the real Macsbug installed. While GraphicsBug does not have any demonstrated circumstances under which it corrupts memory, various commands can cause a crash.
Listing GX Objects
Once you've selected your application heap, you're ready to explore the GX
heap. To get a list of the objects in a GX heap, use hd, for "HeapDump". For
instance, dumping a GX application that has created one
Heap dumps include all blocks allocated by GX, including undocumented internal blocks.
The details of what's in a heap dump are covered in the next section, but there are a few generalities worth noting:
Look at Them Shapes
The easiest way to start a GX heap survey is to get a list of all of the shapes allocated by the application. A number of the commands can have a "shape" qualifier: this restricts the blocks listed to the shapes the application has created. For instance, this code:
Generating one shape in the source code resulted in one shape in the dump; perfectly reasonable. But look what this command tells us:
The other line is the default shape that's used internally by GX. There are a host of circumstances where GX creates internal shapes; the "shape" attribute winnows those internal shapes out.
There are a host of ways to view the contents of a GX object. In this case, the da command (for "display all") is handy:
Like hd, the da command can be used with or without modifiers. More than one modifier acts as an additional qualifier; only objects that meet all the conditions are listed.
You can use the Display Memory
The 't' stands for "typed". Another way to display an object is to option-double click on the address.
The address you have may either be in the object or just associated with it. You can use the WHere command to determine if the address is in any object.
The Find command can be used to determine what objects are associated with an address. Here's a heap dump fragment that shows the address of an ink.
You can use Find to return objects that have references to the ink. Type 'f', then hold down the Command key and click on the "Mstr Ptr" value to copy it to the command line. (If the Command shortcut is stubborn, try clicking in the command line before clicking on the number to copy.)
In this example, there are three references to the ink: the line shape created by the application, the internal default line, and the ink itself. There may be more shapes that use this ink that are not shown by this command. GraphicsBug only searches the RAM-resident graphics heap and does not search the disk-based backing store (where object unloaded to disk reside).
You can qualify Find just like Heap Dump. Here, we request all user allocated shapes that refer to the ink in question:
This completes the indispensable portion of GraphicsBug. If you forget what you've learned so far, just remember to type '?'. This returns a summary of the GraphicsBug commands.
This section spells out what the commands do and how GraphicsBug works.
GraphicsBug and QuickDraw GX
When GraphicsBug launches, it also establishes communication with the rest of GX via a special debugging interface. This means if GX is not around, GraphicsBug may crash.
It's not necessary to have a GX application running to launch GraphicsBug. With only the Graphics debugging INIT installed in your system, the Finder will not be a GX client and GX Printing will not be available, but calls to GX graphics, fonts and text are still available.
As a default, GraphicsBug selects the GX system heap. Analogous to the GX application's heap, the GX system heap has nothing to do with the Macintosh system heap; it is only the container for storing GX objects common to all applications, like the gxViewDevice associated with the screen.
The Zen of Being Up-To-Date
In different releases of GX, the memory blocks visible to GraphicsBug can and do change: note that some of the blocks listed in the previous examples don't have real object names. That's because new internal types were added to GX after GraphicsBug was last revised. This may sound like GraphicsBug is "out of date." In fact, there are two ways GraphicsBug can be out of date. When GraphicsBug is compiled, it includes some part of the GX source base; if it was compiled against a different source base than the one you're running, GraphicsBug is likely to crash and burn on launch or soon afterwards. Also, GraphicsBug has tables of types that are maintained by hand; if these tables are out of date, then some block types can't be displayed. This is less serious, since the block types of interest to most developers have templates which are complete and accurate.
Common Command Summary
GraphicsBug allows you to examine the graphics heap in detail. Here are the commands you're most likely to use:
Switches to the heap containing addr, or named <heapname>. This command works reasonably well from the command line or from the menu. It's OK to quote the <heapname>. If there's no debugging INIT, you can use the LC command to find the heap address of your GX application. You'll want to use HX to select the correct heap before using the other GraphicsBug commands.
Displays all blocks in the heap, or all that match parameters.
Display memory from addr using the appropriate template for that type. Or, option double click on the address to display memory using a template.
Finds references to addr in the heap parts that match parameters.
Dumps the heap, or the heap parts that match parameters.
Displays the block containing addr.
Simple commands like cut-and-paste do not entirely work. GraphicsBug does a terrible job of maintaining the current selection, for instance. There are a few reliable techniques worth knowing:
Uncommon Commands and Command Options
You can stop here. Really. But if you are an information junkie, here are some additional options and commands that may come in handy from time to time.
Somewhat Useful Commands
Displays the error name that matches this number. It's easiest if the number is hexadecimal, but if you precede the number with a number sign, you can enter decimal as well.
Putting the minus sign in front of the number won't work:
What #-26900 evaluates to is anybody's guess.
Find Within Memory Range
You can refine the Find command by specifying the number of items to find, and the address range of those items. The number of items doesn't have any effect, but the start and end range work OK.
If you have the rare bug that corrupts the GX heap, you can use HeapCheck to isolate the offending code.
Special Block Qualifiers
You can qualify
Internally, blocks may be locked down; the bu parameter lists these busy
blocks. You can explicitly lock busy blocks by calling
Validate all blocks (no parameters) or validate a specific block.
These commands you'll likely never need, but for the sake of completeness, here they are. The explanations that follow are sparse, but after all, the commands are practically useless.
The only thing that
Display the stream produced by flattening this shape
Flatten performs the same work as
The numbers in parentheses are data. The numbers in brackets are reference
counts. The numbers after the number sign are stream data sizes, not counting
the stream data two byte header. The "no/byte/word compression" refers to
whether the actual data is larger than the shown data. For instance, the byte
Only data that differs from the INIT default values is written; that's why the style, ink and transform in this example have no data. The line and its companions can be represented in just 21 bytes.
You'll see more of this in Inside Macintosh: GX Environment and
Utilities. If you specify a filename, GraphicsBug will save the flattened
object in binary form in the file. The file type will be "flat". You can pass
this file to the
Display graphics globals
This command usually returns the wrong globals. To get the correct graphics globals, follow these steps instead:
Lists the known heaps.
If you forget the name of your application (and you're running the debug init), this will help refresh your memory.
Without the debug init, only addresses will appear in response to this command.
Displays INIT globals.
These globals are used by all
Lists the known graphics clients.
Lists the known processes, with or without a graphics client.
Unfortunately, this is another command that doesn't work directly. You can get
the correct result though
A more useful way to find errors is to use the
Quits out of GraphicsBug.
The numbers in parentheses are the values in the file, one byte at a time. The numbers in square brackets are the reference indices. Values in curly braces are in decimal fixed point.
Graphics objects default to referring to the last object unflattened; the line in this example refers to the simple style, ink and transform in front of it. A reference allows a shape to refer to some object other than the one immediately before it.
Use the up/down arrow keys to set the scrolling speed.
Use dot '.' to represent the last displayed address.
operators: - + * / % ^ | & [@*] ~ () numbers: . 0x $ # '' strings: ""
You can do simple math expressions in GraphicsBug, and a lot of the time they'll actually work.
Numbers can be entered in hexadecimal (the default), decimal and character codes. You can explicitly enter hexadecimal by preceding it with 0x or $. You can explicitly enter decimal by preceding it with #. If there's no prefix, and the number contains a letter from a to f, then it is treated as hexadecimal. Finally, if the string is simple decimal digits, with or without a decimal point, its treated by default as hexadecimal. Selecting decimal as the integer default in the Preferences dialog changes both integer and fixed point numbers to default to decimal. The fixed point default in the Preferences dialog does nothing.
The results follow C evaluation rules and show the result in hex, decimal fixed point and as characters. You can select whether the hexadecimal uses upper case letters or not in the Preferences dialog.
If you don't enter a leading #, it's interpreted as hexadecimal.
Arithmetic with fixed numbers works by converting the number to a 32 long first.
The first example works; the second does not.
The operators available are basically the same as in Macsbug:
- unary minus or binary subtraction
Things that don't work
what works instead:
Conditional operators like >, <, >=, <=, ==, != work, too.
! doesn't work consistently.
Characters can be used alone or in expressions.
You can enter in more than one expression on the same command line.
Multiple commands can be separated by semicolons. It's the same in Macsbug.
Here's an example that works in both:
The Stuff in the Menus
The File Menu
You can create more than one GraphicsBug window, but if you switch back and forth between them, GraphicsBug may get confused about which window to draw into. It's best to stick to one window. GraphicsBug will successfully remember the size and placement of the window, though.
In addition to opening text files, you can open files created by FLatten, printer spool files and Portable Digital Documents.
This opens a new window and generates object subtotals and totals for files created by FLatten, printer spool files and Portable Digital Documents.
Save, Save As, Save a Copy As, Revert
Save, Save As, and Save a Copy As work. Revert does not work. As we noted before, multiple windows in GraphicsBug is not very functional, so do not be cavalier about saving dumps that you care about.
Page Setup, Print
These commands do not work correctly.
A few preferences work, but most don't. The only part of preferences that is ever worth changing is the size of the window buffer. To save a large heap dump, for instance, increase the size of the window buffer before opening the GraphicsBug window. Other changes that do work on the surface, like changing the Integer default from Hexadecimal to Decimal, goof up commands like Command-clicking on addresses. It's best to ignore Preferences.
Undo never works. Cut, Copy and Paste work somewhat, but be sure to click either above or below the command line first. The most useful command in Edit is Select All; to clear out the info in a GraphicsBug window, click on the content area, execute Select All, then press delete.
These commands are most useful from the command line, but for completeness, they can be chosen from the menu instead. If they usually take an argument, then that argument must be selected in the content area. The most useful of the bunch is Find, which is associated with command-F. You can double click on addresses and Find them in rapid succession.
Similarly, the ERror menu item uses the current selection as the error number to look up; probably useless because the only places error numbers might show up are already translated to strings. Validate might be useful if Validate worked with an argument, but it doesn't, so it isn't. For the rest of the commands, if they work at all (and most don't) there's nothing that they do that can't be done from the command line, or in the case of DisplayMemory, option-double clicking on the address.
The Heap menu has the same interface and caveats as the Command menu. Its useful contribution is the list of heaps that GraphicsBug can operate on at the bottom of the menu. If there's no Debug INIT installed, you'll get numbers instead of names.
Clients, Processes and Windows Menu
These menus are only lists of the graphics clients, Process Manager processes
and windows that GraphicsBug knows about. Clients do the equivalent of a
The first two items, Show Fields and Show Blocks bring up windows that are constantly updated. Neither shows up in the Windows menu, nor behaves very well as windows. For instance, closing the window with the close box may cause GraphicsBug to crash. Use the menu instead. If the windows don't appear when you select them from the menu, they may have been placed behind the text window; try resizing or moving it.
Show Fields shows a constantly updated version of the current heap's header. Unfortunately, it is out of date; some fields are omitted, and others, starting with stackTop are incorrect. It's still useful for monitoring the totalFree field as the application runs.
Show Blocks shows a constantly updated graphic representation of the heap. It's another stillborn GraphicsBug idea; you can't scroll through the blocks, so if the heap is large, you'll only be able to see the first blocks. You can choose Small Blocks and see about a half of a meg. The Update Blocks choice makes the window update as the application runs. The color of the blocks show whether the blocks are direct, indirect or free. The Pattern Blocks menu item shows that when GraphicsBug was created, many of the graphics engineers at Apple were still using black and white monitors. Go figure.
If you click and drag on the blocks in the Show Blocks window, it will show you the block size, type and address.
More GraphicsBug Bugs To Watch Out For
Developer CD Series: Mac OS SDK Edition: Development Kits (Disc 2): QuickDraw GX: Programming Stuff: GX Libraries:
Inside Macintosh: QuickDraw GX Objects
Inside Macintosh: QuickDraw GX Environment and Utilities
Contact ADC | ADC Site Map | ADC Advanced Search
|For information about Apple Products, please visit Apple.com.|
Contact Apple | Privacy Notice
Copyright © 2002 Apple Computer, Inc. All rights reserved.