TweetFollow Us on Twitter

PowerPlant Debugging Classes

Volume Number: 15 (1999)
Issue Number: 5
Column Tag: PowerPlant Workshop

PowerPlant's Debugging Classes

by John C. Daub, Austin, Texas USA

Techniques and tools to help you find and prevent bugs

What We Have Here is a Failure To Deallocate

That line comes from infamous Coolhand Leak (see the help text for the "leaks" 'dcmd'). And like it or not, things like this - bugs - happen. Humans write software, by nature humans make mistakes, so it's a fair bet that there will be mistakes (bugs) in software. Of course no one likes bugs, especially the users of our software, so it behooves us programmers to do our best to write solid and bug-free code. I've found three stages in which the programmer can work to make their code bug free: before, during, and after coding.

Before coding requires proper planning and design in terms of interfaces, implementation, tool selection, and so on. Some would argue this stage is most important as starting off on the wrong foot is more difficult to recover from down the road. During coding involves techniques such as performing assertions to validate arguments and return values, checking for nil, and other processes that you can perform while typing code. After coding involves such things as running under a debugger or stress-testing/validation tool (such as QC or Spotlight), or worst case, receiving a bug report from a user.

The core of PowerPlant mostly offers tools for the "during" stage. Looking in UDebugging and UException, you find the core elements for checking errors, throwing exceptions, and performing Signals (informational messages). These tools provide a good foundation to help you write more solid code, but certainly more can be done. Enter the Debugging Classes.

The Debugging Classes are a fairly recent addition to PowerPlant. They debuted on CodeWarrior Professional 3, but I wasn't happy with their implementation. I have since rewritten the classes, and the fruits of this labor can be seen on Pro 5, which should be on your desk by the time you read this article. In this article, I'd like to introduce you to the Debugging Classes and the wonderful tools they have to offer towards helping you write better code, squash any bugs you may find, and hopefully prevent bugs from happening in the first place. The Debugging Classes don't offer much to help with the "before" stage (aside from the fact you should choose to use them), but they do provide a plethora of tools for the "during" and "after" stage. The Debugging Classes are considered "Advanced Classes," so if you are a PowerPlant newbie, you may wish to get better acquainted with the core and basics of PowerPlant first. But do return to look at the Debugging Classes eventually - they'll help you write better code in the long run. Without further ado, let's dig in!

Overview

The Debugging Classes were written with a few chief goals in mind: to be drop and play, to be flexible, and to be simple yet powerful. The classes needed to be as "drop and play" as possible; that is, they needed to be designed so they could be added to (or removed from) an existing project with minimal effort. The classes are not integrated throughout PowerPlant (at least at this stage) to avoid dependencies upon the classes. This was important as existing projects may have their own debugging mechanisms. It also provides a means for users to try out the classes on their existing project, but if they determine they aren't right for the job, they can easily be removed. Theoretically, to add the classes to an existing project, all one has to do is add the files from the _Debugging Classes folder to a project/target, establish a few macros for third party supports (as laid out in PP_Debug.h), then call LDebugMenuAttachment::InstallDebugMenu() from their Application's Initialize() method:

   void
   CMyApp::Initialize()
   {
   #if PP_Debug
      LDebugMenuAttachment::InstallDebugMenu(this);
   #endif
   }

There are other means of instantiating the Debug menu as well as overall use of the Debugging Classes, but for the newcomer, this is the best place to start.

The Debugging Classes were also designed to be as flexible as possible. When I first wrote the classes, I generated everything at runtime: the windows, the menus, the behaviors. This was done to minimize impact and conflicts with existing projects. However, this method turned out to be less than optimal as it didn't provide a simple means of customization, and it also tied the user to the implementation provided by the Factory (pun intended). For the Pro 5 version of the classes, I removed all of the on-the-fly creation and instead used the tried-and-true Mac method of using Resources. By using Resources, the code is cleaner, the code is smaller, and it's easier to customize. The one downside is the potential for Resource ID's to conflict. To work around this possibility, one can use the factory Resources as a template for your own custom versions. Then when creating the Debug menu, one can fill out an SDebugInfo structure with the relevant information about the Resources. For example, the default 'MENU' ID for the Debug menu is 600. If instead you wished to use 1000, you could create the Debug menu like this:

   void
   CMyApp::Initialize()
   {
   #if PP_Debug
      SDebugInfo      theDebugInfo;
      LDebugMenuAttachment::SetDebugInfoDefaults(theDebugInfo);

      theDebugInfo.debugMenuID = 1000;

      mDebugAttachment = new
                        LDebugMenuAttachment(theDebugInfo);
      ValidateObject_(mDebugAttachment);

      mDebugAttachment->InitDebugMenu();

      AddAttachment(mDebugAttachment);
   #endif
   }

Slightly more code than the previous snippet, but it allows for greater flexibility in the long run. Don't worry if you don't understand everything that's going on just yet. By the end of this article things should look a little more familiar.

Another item of flexibility is the extensive use of macros throughout the classes. The macros are designed to be the point of entry to the Debugging Classes within your code. These macros toggle their behavior based upon the nature of your target: debug build or release/final build. This way you can write your code once, gain full debug features in your debug builds, but have the code stripped out or reverted to a "clean, release" version of the functionality for you release builds. So instead of doing this:

   #if PP_Debug
      LPane*         thePane = theWindow->FindPaneByID(1);
      ThrowIfNil_(thePane);
   
      LCaption*   theCaption = dynamic_cast<LCaption*>(thePane);
      ThrowIfNil_(theCaption);
   #else
      LCaption*   theCaption = dynamic_cast<LCaption*>
                                       (theWindow->FindPaneByID(1));
      ThrowIfNil_(theCaption);
   #endif

you can instead use one of the Debugging Classes macros:

      LCaption*   theCaption =
                  FindPaneByID_(theWindow, 1, LCaption);

You can find FindPaneByID_ and other useful macros in PP_DebugMacros.h, as well as throughout many of the header files like UOnyx and UDebugNew.

The third goal of the classes was to be as simple as possible, yet as powerful as possible. There is a great deal of code involved in the classes, but most of this code you never have to interact with directly. The Tree classes provide a dynamic runtime display of the Commander Chain and Visual Hierarchy. There are many classes and a lot of code to make this magic possible, but all you have to do is select Show Command Chain or Show Visual Hierarchy from the Debug menu - the details are handled for you automatically. Furthermore, if something is better handled by another tool, the Debugging Classes strive to work that tool into PowerPlant instead of reinventing the wheel. UOnyx provides a PowerPlant-savvy interface to Onyx Technology's QC and Spotlight tools. UDebugNew provides a wrapper to DebugNew (a tool for validating C++ pointers), and works with UOnyx to help DebugNew and Spotlight play nice together.

Of course, a final goal of the classes is to help you write better code, and diagnose and fix problems. Now that you've gotten a taste of the classes, let's take a look at the specifics of what the Debugging Classes have to offer.

What's In There?

Support Classes

If you're unfamiliar with the Debugging Classes, you're probably wondering what this Debug menu is. The Debug menu, as implemented by LDebugMenuAttachment, is a special menu added to your Application's MenuBar that provides you with runtime access to many of the Debugging Classes runtime features.


Figure 1. The Debug menu from LDebugMenuAttachment.

The Debugging Classes are designed with the Debug menu as the central point. You don't have to use LDebugMenuAttachment to use the Debugging Classes (many of the classes can be used independently), but LDebugMenuAttachment certainly facilitates things - again I would recommend newcomers to start here and work on customization after you're more familiar with the classes.

From the Debug menu, you can: break into a Debugger; launch helper applications like ZoneRanger (on the CW Pro Mac Tools CD) or HeapBoss (from Biit, Inc); display the Command Chain and Visual Hierarchy (Tree Classes); perform heap manipulations (compact, purge, scramble, via UHeapUtils and LHeapAction); interact with DebugNew (UDebugNew); interact with QC (UOnyx); manipulate the values of gDebugThrow and gDebugSignal (UDebugging); consume memory (UMemoryEater); and validate your PPob Resources (UValidPPob). One of the advantages to the menu is that some of these values normally have no runtime interface, e.g. gDebugThrow/gDebugSignal or DebugNew; to manipulate these values you have to change your code, recompile, and re-run. However through the Debug menu, you can manipulate these values at runtime with no need to recompile your project/target.

Another part of the Support Classes is LHeapAction. LHeapAction is a Periodical object that performs certain actions on a given heap (typically the Application's heap). These actions include compacting, purging, compacting and purging (at the same time), and if QC support is enabled, performing a heap consistency check, bounds checking, and a heap scramble. You can access these actions and modify their frequency via the Debug menu.


Figure 2. HeapAction submenu.

To perform such actions on your heap, either immediately or periodically, is a boon towards helping you locate stale Handle usage, avoiding problems with cached Resources, and overall stress-testing your Application.

Stream Classes

There's actually only one Stream Class, LDebugStream, but the utility of this class cannot be underestimated. Those of you that use the "debugging by printf" technique will find LDebugStream a useful feature. LDebugStream is a Stream class that sends data to a debugging location. This location (EFlushLocation) can be a debugger, a file, the mechanism used by gDebugThrow or gDebugSignal, or to a console such as the SIOUX console window (the ability to flush to a console is new in Pro 5). One item of note is that LDebugStream does not inherit from LStream; this is intentional as an LStream can be two-ways (in and out), but LDebugStream is one-way (out, to the EFlushLocation). Furthermore, LStream is oriented towards binary streams, whereas LDebugStream outputs ASCII text.

LDebugStream provides many methods and operator overloads to ease streaming. There are numerous Write methods for many data types both basic (integers, bool's) and Mac-specific (Rect, Point, RGBColor, RgnHandle, FourCharCode, NumVersion, Fixed). When these data types are written, they are written in a useful human-readable manner. For example, outputting a Point would generate the line:

   Point - v: 15 h: 20

LDebugStream also provides detailed information about raw Handle's and Ptr's via the Dump methods. These Dump methods were introduced in Pro 5, and not only provide a raw look at the memory, but also useful information about the memory, especially useful with Handle's. A DumpHandle_() of STRx_Standards yields this result:

--------------------------------------
"PP Debug Tester DEBUG PPC" debug log for Sun, Mar 7, 1999 4:23:13 PM
--------------------------------------

Results of Handle dump. FILE: "CDebugApp.cp" LINE: 347
   Address: 0x1E30BA4 | Master pointer: 0x1E47F40 |          Handle data size: 97 | State: UPR
   Resource Info - Type: 'STR#' ID: 200 Name: Standards
   Resource Attributes - SysRef: OFF SysHeap: OFF          Purgeable: ON Locked: OFF Protected: 
      OFF Preload: OFF Changed: OFF
Results of Raw dump. FILE: "CDebugApp.cp" LINE: 347
   Dumping 97 bytes of memory starting at address:          0x1E47F40
   OFFSET     | CONTENTS (HEX)                          | CONTENTS (ASCII)
   ------------------------------------
   0x00000000 | 0004 1644 6562 7567 6769 6E67 2043 6C61 | ...Debugging Cla
   0x00000010 | 7373 6573 2044 656D 6F0D 5361 7665 2046 | sses Demo.Save F
   0x00000020 | 696C 6520 4173 3A1C 4F70 656E 3A20 4465 | ile As:.Open: De
   0x00000030 | 6275 6767 696E 6720 436C 6173 7365 7320 | bugging Classes 
   0x00000040 | 4465 6D6F 1C53 6176 653A 2044 6562 7567 | Demo.Save: Debug
   0x00000050 | 6769 6E67 2043 6C61 7373 6573 2044 656D | ging Classes Dem
   0x00000060 | 6F                                      | o               
End Raw dump. FILE: "CDebugApp.cp" LINE: 347

End Handle dump. FILE: "CDebugApp.cp" LINE: 347

In this dump you can see information such as the address of the Handle and its master pointer, the size of the Handle, its state (lock, purgable, resource), and the raw memory contents. As well, if the Handle is a Resource Handle, information about the Resource and its attributes are listed for your edification. Notice as well that DumpHandle_() is a macro. As was mentioned previously, the Debugging Classes provide macros for ease of use. See LDebugStream.h for more DebugStream macros.

Tree Classes

The Tree Classes are one of the niftier portions of the Debugging Classes, as well as the most common reason for PowerPlant users to start using the Debugging Classes (since everyone seems to run into a Commander Chain problem sooner or later). Long long ago in a cubicle far far away from mine, Greg Bolsinga (Metrowerks' Class Wrangler Wrangler) had problems with his Commander Chain. He hacked up a utility that would display the Commander Chain in a Pane at runtime. Since it helped him solve his problem, Greg passed his (admitted) hack along to me to see what we could do with it officially for PowerPlant. We placed it on CW Pro 2 as an example, but there the seed was sown for the Debugging Classes. Since that time, LCommanderTree has been cleaned up and fleshed out with more functionality than the original, abstracted back to a more common base class (LTree), and from there subclassed to also provide information about the Visual Hierarchy (LPaneTree). In addition to displaying the Visual Hierarchy of the frontmost regular or modal window, LPaneTree also displays Attachment and Broadcaster/Listener information.


Figure 3. LCommanderTree and LPaneTree in action.

Looking at Figure 3 you can see the Trees display a great deal of information about the respective Tree. First, each LTreeWindow contains a set of controls across the top to allow you to manipulate the Tree/Window's behavior. You can set the Tree to automatically refresh at a certain interval (this interval is currently set via the Debug menu), or to refresh immediately. You can save the current Tree to a file (internally using LDebugStream), and you can also toggle the extra information (such as the Attachment and Broadcaster/Listener information) on and off as it is optional information and can clutter the screen.

The CommanderTree provides you with a visual representation of your Application's Commander Chain. Each level of indentation represents a level down the chain, and only objects inheriting from LCommander are displayed. For each object, its name is given as well as its Commander duty state. If the object is also a Pane, it's PaneIDT is listed. Text styles are used to designate the on-duty chain, the target, and any latent Commanders; the styles are bold, red color, and italics, respectively, by default, but you can customize these styles as you wish.

The PaneTree provides you with a representation of the Visual Hierarchy of the frontmost window in the regular or modal layer (floating windows are not supported by default as targeting floaters is tricky to do). Basic Pane information is provided, such as object name, PaneIDT, state (active, enable, visible), and descriptor. If you turn on the display of extra information, any Attachments on the Pane will be listed (along with basic Attachment information such as its Message and the value of mExecuteHost). If the Pane is a Broadcaster its Listeners will be listed, and if the Pane is a Listener its Broadcasters will be listed. One additional feature of LPaneTree is that the (deepest sub-) Pane currently being moused over will be colored in green (by default, user customizable) to aid in identifying Panes at runtime - especially useful if you create your Views on the fly.

Headers

There are three header files used throughout the Debugging Classes: PP_Debug.h, PP_DebugConstants.h, and PP_DebugMacros.h. PP_Debug.h is akin to PP_Prefix.h in that every file in the Debugging Classes somehow #includes this file. It is also similar to PP_Macros.h in that PP_Debug.h contains the macros used to establish the state of feature support within the Debugging Classes; this mostly pertains to third party supports (QC, Spotlight, MoreFiles, DebugNew). PP_DebugConstants.h contains the constants used by the Debugging Classes. Most of this file you do not need to concern yourself with, however one item of note is that the CommandT range of 600-799 inclusive is reserved for use by the Debugging Classes. Fortunately, this range is within the range of PowerPlant's reserved CommandT's (-999 to 999 inclusive) so you shouldn't run into any conflicts.

The PP_DebugMacros.h file is certainly the most interesting file of the three global headers. Within this file are many useful macros that you can and should use throughout your code. There are validation macros: ValidatePtr_(), ValidateHandle_(), ValidateObject_(), ValidateSimpleObject_(). These validation macros ensure the given variable is valid by performing nil checks and using QC and DebugNew if those supports are enabled. You should use these macros whenever you allocate memory/objects or when the state of memory/object could be in question. Also within the file are assertion macros: AssertHandleLocked_() ensures the given Handle is locked, AssertHandleUnlocked_() ensures the given Handle is unlocked, AssertHandleResource_() ensures the given Handle is a Resource Handle, and AssertHandleMemory_() ensures the given Handle is a Memory Handle. As these macros are assertions, they will be preprocessed out of release/final builds. The Verify_() macro used to be a synonym for Assert_(), but in Pro 5 its behavior changed slightly. It still performs an assertion, but now the Verify_() statement is not preprocessed away in release/final builds. The DisposeOf_() suite of macros are used in place of delete. In debug builds, the pointer is validated, delete is called, and the pointer variable is set to nil; in release/final builds, the pointer is deleted and the variable set to nil.

Although the Debugging Classes are currently and mostly separate from the rest of PowerPlant, certain ideas have found their way into the core of PowerPlant. One of these are the Suppression macros: StDisableDebugThrow_(), StDisableDebugSignal_(), StChangeDebugThrow_(), and StChangeDebugSignal_(). These macros temporarily modify the EDebugAction of gDebugThrow or gDebugSignal. The Disable macros set the EDebugAction to debugAction_Nothing, and the Change macros set the EDebugAction to whatever new EDebugAction is specified. You'd want to use these macros in situations where a Throw_() or Signal_() might occur but you don't want PowerPlant's UDebugging mechanisms to kick in.

   try {
      StDisableDebugThrow_();

         // This will ThrowIfOSErr_(memFullErr); if we
         // run out of memory.
      DoSomethingMemoryIntensive();
   } catch (LException& iErr) {

            // No problems. Running out of memory isn't
            // fatal.
      if (iErr.GetErrorCode() != memFullErr) {
         throw;      // rethrow
      }
   }

In the above snippet, I know it's possible to run out of memory. I want this situation to be handled and the exception to still be thrown, but I don't want to hear about it (I don't want to break into the debugger or have the Throw 'ALRT' displayed). By using StDisableDebugThrow_() the UDebugging functionality is temporarily suppressed. It is important to note the "St" designation of the macros - they do behave like stack-base classes; in fact, they use StValueChanger (UMemoryMgr.h) to accomplish their task.

Finally, PP_DebugMacros.h contain some useful macros that replace the tedium of FindPaneByID and dynamic_cast's. Typically one calls FindPaneByID() along these lines:

   LCaption* theCaption = dynamic_cast<LCaption*>
                                       (theWindow->FindPaneByID(1));
   ThrowIfNil_(theCaption);

This code sequence does work, but there is a hidden chance for failure: if FindPaneByID() does not find the Pane it returns nil, and then the dynamic_cast will fail as well (although it is safe to dynamic_cast a nil pointer). The problem is that you cannot tell from the ThrowIfNil_() if the failure was due to FindPaneByID() failing or the dynamic_cast failing. FindPaneByID_() alleviates this ambiguity by first performing a FindPaneByID() and validating that result. If the result is good, then the dynamic_cast is performed and that result is validated as well. Along the way, any failures are noted for exactly the source of the failure to help you better pinpoint the source of the failure. The improved code is:

   LCaption*   theCaption =
                  FindPaneByID_(theWindow, 1, LCaption);

There is also a FindPaneByIDNoThrow_() variant that raises a Signal instead of Throwing, and returns nil upon failure.

The DebugCast_() and DebugCastNoThrow_() macros perform a dynamic_cast of one pointer to another (it does not handle dynamic_cast'ing of references). They validate the arguments and report the error by Throwing or Signaling. These four macros not only provide a more robust means of performing their functionality, but it's a lot easier to type the one line of code. :-)

Resources

This portion of the Debugging Classes is fairly straightforward. DebugTrees.CTYP contains the CTYP's for the Tree classes (LTree, LPaneTree, LCommanderTree, LTreeWindow). If it's not already there, place this file into the Custom Types folder within the Metrowerks PowerPlant folder of your CodeWarrior installation (this is the same folder where the Constructor application resides). It is not essential to add this file to your project/target, but you're welcome to do so if you wish to include the 'CTYP' Resources in your binaries.

PP Debug Support.ppob and PP Debug Support.rsrc contain vital Resources used by the Debugging Classes. PP Debug Support.ppob file contains the default 'PPob', 'MENU', and 'Txtr' Resources used by the various c lasses. You can add this file as-is to your project/target, or you can copy the Resources to your own file and customize them as you wish. PP Debug Support.rsrc contains the nifty debug icon used as the menu title for the Debug menu (optional, cosmetic) and contains replacement Resources for the ThrowAt and SignalAt alerts (as found in PP DebugAlerts.rsrc). These replacement Resources are used in conjunction with UDebuggingPlus.cp, which we'll discuss in the next subsection. You're welcome to use the Resources as-is or customize them as you wish.

Utility Classes

The Debugging Classes contain many utility classes and namespaces to help in your coding efforts. UDebuggingPlus.cp is a replacement for UDebugging.cp. Both files implement the UDebugging namespace, but only one file can be within your project at a time (this is akin to how UDesktop.cp and UFloatingDesktop.cp work). Before Pro 5, UDebugging's ThrowAt and SignalAt alerts (as found in PP DebugAlerts.rsrc) would display the alert, and the only action you could take in response to the alert was to click OK and proceed in whatever manner the flow of the code would take you. This wasn't always optimal. UDebuggingPlus.cp (and PP Debug Support.rsrc) were written to provide you with greater options upon receiving the ThrowAt or SignalAt alerts.


Figure 4. Improved SignalAt alert.

In Figure 4 you can see the additional options provided by the improved UDebuggingPlus. Continue did just that - continue execution. Quit immediately calls ExitToShell. Debugger breaks into a debugger, Quiet changes the respective EDebugAction to debugAction_Nothing, and Log outputs the data from the Signal or Throw to a file via LDebugStream. Furthermore, the whitespace given to display the condition/error code is larger than the original alerts to allow for more error text. Although Figure 4 shows the SignalAt alert, the ThrowAt alert is the same in terms of functionality.

As of Pro 5, UDebugging and PP DebugAlerts.rsrc now support most of the functionality provided by UDebuggingPlus/PP Debug Support.rsrc. However, as of this writing, the Log functionality is missing. When all of UDebuggingPlus' functionality is moved into UDebugging, UDebuggingPlus will be obsoleted.

UDebugNew provides a wrapper for DebugNew, mostly to enable DebugNew and Spotlight to work together (as DebugNew does funky yet kosher things that Spotlight would otherwise complain about). UDebugNew also contains various macros to facilitate using DebugNew in your code, interfaces are given to aspects of DebugNew that don't have interfaces, removes the tedium of remembering what is and is not supported in DebugNew based upon the setting of DEBUG_NEW, and provides a more PowerPlant-savvy error handler. As of this writing Metrowerks is working on a replacement and improvement for DebugNew called DebugMem. Eventually support for DebugMem will be added to the Debugging Classes, but this support is not part of Pro 5.

UDebugUtils is a collection of sundry utilities. CheckEnvironment() examines your environment at runtime and alerts you to any potentially problem situations, such as not having a debugger installed. It is not required to call CheckEnvironment(), but it is highly recommended to do so. A good place to call it is immediately after Toolbox initialization. Debugger() and DebugStr() are replacements for the Toolbox traps of the same name. These versions however check for the presence of a debugger before calling the Toolbox trap to avoid any ugly crashes. UDebugUtils.h contains wrapper macros for the Debugger traps: PP_Debugger_() and PP_DebugStr_() go through the UDebugUtils bottlenecks, and Debugger_() and DebugStr_() call straight to the Toolbox. The advantage of these macros is that they will be preprocessed out of final/release builds. How many times have you inadvertently left a DebugStr call in your release builds?

UHeapUtils provides means for manipulating heaps. You can compact, purge, and scramble your heaps. Compacting and purging is accomplished through Toolbox routines, but scrambling is a bit odd. If QC is present, then QC's scrambling mechanisms are used. But if QC is not present, DebugStr's are used to drop into MacsBug to use its heap scrambling functionality. It's a little ugly, but it works. There's no excuse not to scramble your heap as it will sooner or later turn up problems (don't forget about LHeapAction).

UMemoryEater helps you simulate low-memory situations by consuming memory.


Figure 5. Eat Memory dialog.

When you select Eat Memory... from the Debug menu, the dialog in Figure 5 is displayed. You can specify the number of bytes to eat and what type of memory to eat: Handle (relocatable) or Ptr (non-relocatable). This functionality is best used with ZoneRanger to keep an eye on the exact state of your heap as you consume memory. It is important to test your Application's functionality in low-memory situations. LGrowZone can help, but it is only one part of a good low-memory handling strategy.

UOnyx provides wrappers for Spotlight and QC from Onyx Technology. Use of UOnyx is optional, which is important if you do not own QC and/or Spotlight. The key features of UOnyx are the famous macros to aid in supporting QC/Spotlight in debug builds but is removed from release builds, and wrappers for the QC API to facilitate its ease of use and make it more PowerPlant-savvy. The QC and Spotlight products and API's are not provided by Metrowerks; you must purchase these products separately from Onyx Technology.

UProcess is a wrapper for the Process Manager that strives to make using the Process Manager a bit easier. This class can be used independent of the Debugging Classes, as its functionality certainly extends beyond the bounds of debugging. UVolume contains utility functions for working with volumes. It is not a complete class by any means. UVolume (and UProcess as well) were actually written to aid in the implementation of LDebugMenuAttachment's feature for launching ZoneRanger and HeapBoss. See UVolume::FindApp() and UProcess::LaunchApp() to see how these fit together.

Finally, UValidPPob provides a means for validating the data within your 'PPob' Resources.


Figure 6. Validate PPob dialog.

Currently it looks at what classes are within a specified PPob (specified by the dialog in Figure 6), compares this list to the URegistrar table, and any unregistered classes are reported via a Signal_(). A ValidateAllPPobs() method is provided as well to validate every PPob, and the results of this validation are streamed to a file via LDebugStream. Currently UValidPPob can only list what is in a PPob but not registered. The other direction, listing what is registered but not in any PPob ("over-registration") cannot be cleanly done. One key reason is the Appearance Classes, which register the Implementation classes but these classes never appear in any PPob DataStream.

Project Stationery, Sample Code, & Documentation

The last part of the Debugging Classes are non-source code support files. For Pro 5, the PowerPlant project stationery has been revamped. The old standbys of Basic, Document, Appearance, and Network remain, and a new "Advanced Stationery" has been introduced. This stationery is geared towards the serious new project. It includes most of the core PowerPlant files, Thread Classes, Table Classes, Appearance Classes, and of course the Debugging Classes. The project and default sources are also set for debug and release targets. Debug targets turn compiler optimizations off and debug information on, while release targets turn compiler optimizations on and debug information off. The default Application object class contains a fair amount of debugging infrastructure to help you get started, using the Debugging Classes and MetroNub Utilities (see the (Debugger Extras) folder in your CodeWarrior install). One extra file in the Advanced Stationery is PPDebug_New.cp. This file implements global replacements for all variants of operators new and delete. These implementations utilize DebugNew and the Debugging Classes to make the operators more robust and better integrated with PowerPlant and your project. Also provided is PP_NewHandler(), a PowerPlant-savvy C++ new_handler (see §18.4.2.2 in the C++ language standard).

Also new in Pro 5 is documentation on the Debugging Classes. A chapter on the Debugging Classes has been added to the PowerPlant Advanced Topics manual. You've probably noticed this article does not contain any tutorials nor in-depth HOWTO's for using the Debugging Classes. This was an intentional decision as the chapter and its accompanying example code do a good job to get you going in using the Debugging Classes. If this article has sparked your interest in these classes, your next stop should be reading this chapter and doing its example code.

Customization

I'd like to briefly touch on the subject of customizing the classes. Before you consider customizing the classes, first take the time to familiarize yourself with the classes and tools as provided from the Factory. I tried to minimize the need for customization, so try out the defaults and find what works for you and what you might wish to improve upon.

One area that I personally would customize is the Debug menu itself. The most useful customization might be adding keyboard shortcuts to commands you frequently use, as always going to the menu can be a bit tedious (I'm one of those people that prefer the keyboard over the mouse). Another might be adding your own commands to the menu to help you execute test code or start a specific chain of events. Regardless of what you do, don't modify the default Resources and Resource/source files. Instead, make copies of the relevant Resource or subclass the sources local to your project and modify those instead. Better still, consider making your own project stationery that contains all of your customizations so every new project you create will be established just as you like it from the onset.

Futures

The Debugging Classes shipped in the _In Progress folder on CodeWarrior Professional 5, but the classes are fairly robust and stable. I do not anticipate a great deal of changes to them in the future. Certainly rough edges will be smoothed, user feature requests will be considered, and any bugs found (heaven forbid ;-) will of course be fixed. One outstanding issue is the integration of the classes throughout the core of PowerPlant; the jury is still out on this one. The classes will need to fully stabilize first as well as weighing the potential impact integration could have upon existing source bases. I'd also like to see about adding supports for more third party products, such as HeapManager. Of course these are all hopes and dreams and by no means constitute any sort of promise nor guarantee they actually will happen (although I hope they will :-).

One point of definite uncertainty is how the Debugging Classes will evolve in terms of Carbon and Mac OS X. Some of the Debugging Classes technology is centered around the Mac OS of today, both in terms of low-level supports, like UDebugUtils, and higher-level assumptions, like UHeapUtils. Some classes should go across with no problems (Trees), some may need to be modified slightly (the Raw methods in LDebugStream), some may become moot (UHeapUtils), and others are totally unknown at this time (UDebugUtils). We'll just have to wait and see how Carbon and OS X shape up before the fate of the Debugging Classes can be fully determined.

Conclusion

I hope you've enjoyed this article on the PowerPlant Debugging Classes. They've certainly been one of the most fun bits of PowerPlant I've written, and IMHO one of the more useful. If you haven't used the Debugging Classes before, please do give a read over their chapter in the Advanced Topics manual and give them a try. If you have used the Debugging Classes, try out an aspect that you may not have used yet, like the various macros. And if you wish, feel free to email me with any stories of how the Debugging Classes helped you, feature requests, bug reports, and even flames (but I hope there aren't many of those).

Good luck, happy programming, and I hope you find the Debugging Classes a helpful, useful, and essential part of your toolbox.

Bibliography


John C. Daub spends a lot of time working on PowerPlant. When he's not writing code for Metrowerks, he writes a lot of his own PowerPlant classes for the Contributed Class archives. John's seen a lot of code in his days, and they are part of the inspiration behind the Debugging Classes. John is also still using System 7.6.1 at home, so please don't complain about the screenshots. You can reach John at hsoi@pobox.com.

 
AAPL
$97.02
Apple Inc.
-0.17
MSFT
$44.46
Microsoft Corpora
-0.41
GOOG
$593.93
Google Inc.
-2.05

MacTech Search:
Community Search:

Software Updates via MacUpdate

Audio Hijack Pro 2.11.0 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Intermission 1.1.1 - Pause and rewind li...
Intermission allows you to pause and rewind live audio from any application on your Mac. Intermission will buffer up to 3 hours of audio, allowing users to skip through any assortment of audio... Read more
Airfoil 4.8.7 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
Microsoft Remote Desktop 8.0.8 - Connect...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
xACT 2.30 - Audio compression toolkit. (...
xACT stands for X Aaudio Compression Toolkit, an application that encodes and decodes FLAC, SHN, Monkey’s Audio, TTA, Wavpack, and Apple Lossless files. It also can encode these formats to MP3, AAC... Read more
Firefox 31.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals... Read more
Little Snitch 3.3.3 - Alerts you to outg...
Little Snitch gives you control over your private outgoing data. Track background activityAs soon as your computer connects to the Internet, applications often have permission to send any... Read more
Thunderbird 31.0 - Email client from Moz...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Together 3.2 - Store and organize all of...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Smart storage. With simple drag-and-drop functionality,... Read more
Cyberduck 4.5 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more

Latest Forum Discussions

See All

LEX Goes Free For One Day In Honor of Ne...
LEX Goes Free For One Day In Honor of New Update Posted by Jennifer Allen on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Thomas Was Alone Goes Universal, Slashes...
Thomas Was Alone Goes Universal, Slashes Price to $3.99 Posted by Ellis Spice on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Meerkatz Challenge Review
Meerkatz Challenge Review By Jennifer Allen on July 24th, 2014 Our Rating: :: FONDLY PUZZLINGUniversal App - Designed for iPhone and iPad Cute and challenging, Meerkatz Challenge is a fun puzzle game, particularly for fans of... | Read more »
Book Your Appointment with F.E.A.R. this...
Book Your Appointment with F.E.A.R. | Read more »
It Came From Canada: Epic Skater
For all the hate that it gets for being a pastime for slackers, skateboarding really does require a lot of skill. All those flips and spins take real athleticism, and there’s all the jargon to memorize. Fortunately for us less extreme individuals,... | Read more »
Cultures Review
Cultures Review By Jennifer Allen on July 24th, 2014 Our Rating: :: SLOW-PACED EMPIRE BUILDINGiPad Only App - Designed for the iPad Cute it might seem, but Cultures is a bit too slow paced when it comes to those pesky timers to... | Read more »
More Paintings Have Been Added to Paint...
More Paintings Have Been Added to Paint it Back! Posted by Jessica Fisher on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
The Order of Souls Review
The Order of Souls Review By Campbell Bird on July 24th, 2014 Our Rating: :: STORY GRINDUniversal App - Designed for iPhone and iPad The Order of Souls is a free-to-play, turn-based RPG with a genre-mixing art style, interesting... | Read more »
Revolution 60 Review
Revolution 60 Review By Jordan Minor on July 24th, 2014 Our Rating: :: LASS EFFECTUniversal App - Designed for iPhone and iPad Revolution 60 is a bold, cinematic action game with ambition to spare.   | Read more »
Matter (Photography)
Matter 1.0.1 Device: iOS Universal Category: Photography Price: $1.99, Version: 1.0.1 (iTunes) Description: Add stunning 3D effects to your photos with real-time shadows and reflections. Export your creations as photos or video loops... | Read more »

Price Scanner via MacPrices.net

What Should Apple’s Next MacBook Priority Be;...
Stabley Times’ Phil Moore says that after expanding its iMac lineup with a new low end model, Apple’s next Mac hardware decision will be how it wants to approach expanding its MacBook lineup as well... Read more
ArtRage For iPhone Painting App Free During C...
ArtRage for iPhone is currently being offered for free (regularly $1.99) during Comic-Con San Diego #SDCC, July 24-27, in celebration of the upcoming ArtRage 4.5 and other 64-bit versions of the... Read more
With The Apple/IBM Alliance, Is The iPad Now...
Almost since the iPad was rolled out in 2010, and especially after Apple made a 128 GB storage configuration available in 2012, there’s been debate over whether the iPad is a serious tool for... Read more
MacBook Airs on sale starting at $799, free s...
B&H Photo has the new 2014 MacBook Airs on sale for up to $100 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels... Read more
Apple 27″ Thunderbolt Display (refurbished) a...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more
WaterField Designs Unveils Cycling Ride Pouch...
High end computer case and bag maker WaterField Designs of San Francisco now enters the cycling market with the introduction of the Cycling Ride Pouch – an upscale toolkit with a scratch-free iPhone... Read more
Kingston Digital Ships Large Capacity Near 1T...
Kingston Digital, Inc., the Flash memory affiliate of Kingston Technology Company, Inc.,has announced its latest addition to the SSDNow V300 series, the V310. The Kingston SSDNow V310 solid-state... Read more
Apple’s Fiscal Third Quarter Results; Record...
Apple has announced financial results for its fiscal 2014 third quarter ended June 28, 2014, racking up quarterly revenue of $37.4 billion and quarterly net profit of $7.7 billion, or $1.28 per... Read more
15-inch 2.0GHz MacBook Pro Retina on sale for...
B&H Photo has the 15″ 2.0GHz Retina MacBook Pro on sale for $1829 including free shipping plus NY sales tax only. Their price is $170 off MSRP. B&H will also include free copies of Parallels... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more

Jobs Board

Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
Senior Interaction Designer, *Apple* Online...
**Job Summary** Apple is looking for a hands on Senior…will be a key player in designing for the Apple Online Store. The ideal designer will have a Read more
*Apple* Sales Chat Rep - Apple (United State...
…is looking for motivated, outgoing, and tech savvy individuals who want to offer Apple Customers an unparalleled customer experience over chat. At Apple , we believe Read more
Mac Expert - *Apple* Online Store Mexico -...
…MUST be fluent in English and Spanish to be considered for this position At Apple , we believe that hard work, a fun environment, creativity and innovation fuel the Read more
*Apple* Industrial Design CAD Sculptor - App...
**Job Summary** The Apple Industrial Design team is looking for a CAD sculptor/Digital 3D modeler to create high quality CAD models used in the industrial design process Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.