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.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Tokkun Studio unveils alpha trailer for...
We are back on the MMORPG news train, and this time it comes from the sort of international developers Tokkun Studio. They are based in France and Japan, so it counts. Anyway, semantics aside, they have released an alpha trailer for the upcoming... | Read more »
Win a host of exclusive in-game Honor of...
To celebrate its latest Jujutsu Kaisen crossover event, Honor of Kings is offering a bounty of login and achievement rewards kicking off the holiday season early. [Read more] | Read more »
Miraibo GO comes out swinging hard as it...
Having just launched what feels like yesterday, Dreamcube Studio is wasting no time adding events to their open-world survival Miraibo GO. Abyssal Souls arrives relatively in time for the spooky season and brings with it horrifying new partners to... | Read more »
Ditch the heavy binders and high price t...
As fun as the real-world equivalent and the very old Game Boy version are, the Pokemon Trading Card games have historically been received poorly on mobile. It is a very strange and confusing trend, but one that The Pokemon Company is determined to... | Read more »
Peace amongst mobile gamers is now shatt...
Some of the crazy folk tales from gaming have undoubtedly come from the EVE universe. Stories of spying, betrayal, and epic battles have entered history, and now the franchise expands as CCP Games launches EVE Galaxy Conquest, a free-to-play 4x... | Read more »
Lord of Nazarick, the turn-based RPG bas...
Crunchyroll and A PLUS JAPAN have just confirmed that Lord of Nazarick, their turn-based RPG based on the popular OVERLORD anime, is now available for iOS and Android. Starting today at 2PM CET, fans can download the game from Google Play and the... | Read more »
Digital Extremes' recent Devstream...
If you are anything like me you are impatiently waiting for Warframe: 1999 whilst simultaneously cursing the fact Excalibur Prime is permanently Vault locked. To keep us fed during our wait, Digital Extremes hosted a Double Devstream to dish out a... | Read more »
The Frozen Canvas adds a splash of colou...
It is time to grab your gloves and layer up, as Torchlight: Infinite is diving into the frozen tundra in its sixth season. The Frozen Canvas is a colourful new update that brings a stylish flair to the Netherrealm and puts creativity in the... | Read more »
Back When AOL WAS the Internet – The Tou...
In Episode 606 of The TouchArcade Show we kick things off talking about my plans for this weekend, which has resulted in this week’s show being a bit shorter than normal. We also go over some more updates on our Patreon situation, which has been... | Read more »
Creative Assembly's latest mobile p...
The Total War series has been slowly trickling onto mobile, which is a fantastic thing because most, if not all, of them are incredibly great fun. Creative Assembly's latest to get the Feral Interactive treatment into portable form is Total War:... | Read more »

Price Scanner via MacPrices.net

Early Black Friday Deal: Apple’s newly upgrad...
Amazon has Apple 13″ MacBook Airs with M2 CPUs and 16GB of RAM on early Black Friday sale for $200 off MSRP, only $799. Their prices are the lowest currently available for these newly upgraded 13″ M2... Read more
13-inch 8GB M2 MacBook Airs for $749, $250 of...
Best Buy has Apple 13″ MacBook Airs with M2 CPUs and 8GB of RAM in stock and on sale on their online store for $250 off MSRP. Prices start at $749. Their prices are the lowest currently available for... Read more
Amazon is offering an early Black Friday $100...
Amazon is offering early Black Friday discounts on Apple’s new 2024 WiFi iPad minis ranging up to $100 off MSRP, each with free shipping. These are the lowest prices available for new minis anywhere... Read more
Price Drop! Clearance 14-inch M3 MacBook Pros...
Best Buy is offering a $500 discount on clearance 14″ M3 MacBook Pros on their online store this week with prices available starting at only $1099. Prices valid for online orders only, in-store... Read more
Apple AirPods Pro with USB-C on early Black F...
A couple of Apple retailers are offering $70 (28%) discounts on Apple’s AirPods Pro with USB-C (and hearing aid capabilities) this weekend. These are early AirPods Black Friday discounts if you’re... Read more
Price drop! 13-inch M3 MacBook Airs now avail...
With yesterday’s across-the-board MacBook Air upgrade to 16GB of RAM standard, Apple has dropped prices on clearance 13″ 8GB M3 MacBook Airs, Certified Refurbished, to a new low starting at only $829... Read more
Price drop! Apple 15-inch M3 MacBook Airs now...
With yesterday’s release of 15-inch M3 MacBook Airs with 16GB of RAM standard, Apple has dropped prices on clearance Certified Refurbished 15″ 8GB M3 MacBook Airs to a new low starting at only $999.... Read more
Apple has clearance 15-inch M2 MacBook Airs a...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs now available starting at $929 and ranging up to $410 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at... Read more
Apple drops prices on 13-inch M2 MacBook Airs...
Apple has dropped prices on 13″ M2 MacBook Airs to a new low of only $749 in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, now available for $679 for 8-Core CPU/7-Core GPU/256GB models. Apple’s one-year warranty is included, shipping is free, and each... Read more

Jobs Board

Seasonal Cashier - *Apple* Blossom Mall - J...
Seasonal Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Seasonal Fine Jewelry Commission Associate -...
…Fine Jewelry Commission Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) Read more
Seasonal Operations Associate - *Apple* Blo...
Seasonal Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.