TweetFollow Us on Twitter

PowerPlant Workshop

Volume Number: 17 (2001)
Issue Number: 05
Column Tag: PowerPlant Workshop

Debugging Basics

by Aaron Montgomery

How one goes about writing a PowerPlant application

These Articles

This is the second article in a series of articles about Metrowerks’ PowerPlant application framework. The first article provided an introduction to how the framework deals with commands. This article focuses on the debugging classes in the framework. This series assumes familiarity with the C++ language, the Macintosh Toolbox API and the CodeWarrior IDE. The articles were written using CodeWarrior 6 with the net-update to IDE 4.1.0.3 and no other modifications.

Why Debugging Now?

There are (at least) three reasons not to do debugging so early in this series of articles. First, debugging doesn’t directly solve the problem of writing the code for the application. Second, the debugging classes use a lot of advanced PowerPlant concepts. Third, the debugging classes are in the _In Progress folder and they may change dramatically between CodeWarrior releases. However, there are (at least) two better reasons to talk about debugging now instead of waiting. First, debugging code should be written as the program is written instead of retrofitting it to existing code. Second, the debugging tools can also be used to learn about how the framework operates. In particular, the debugging classes in PowerPlant can be used to examine the command chain (discussed in the first article) and the visual hierarchy (which will be discussed in third article).

Article Layout

Instead of following the code straight through from start to finish, this article is organized by topic. We will quickly describe changes to the project and the main() function. Most of this can be transplanted from one project to the next without modification. Then we will cover the various facets of the Debugging Classes. It is probably best to read this article at least twice since many times topics will appear in the text prior to the point where they are explained.

Changes To the Project

Although the project for the first article had both a Debug and Final build, there was little to distinguish them from each other. When setting up the debug projects you will need to include the Debugging Classes (which are included in the Advanced stationary option). If you are attempting to add these classes to an existing project, you need to b a little careful. The files UDebugging.cp and UDebuggingPlus.cp implement the same functions. You should include UDebugging.cp in the Final builds and UDebuggingPlus.cp in the Debug builds. The resource files PP Debug Alerts.rsrc and PP Debug Support.rsrc also duplicate resources, the first should be used in the Final builds and the second in the Debug builds. I also did the same for the LDebugStream class: the header LDebugStream.h has two implementations: LDebugStream.cp for Debug builds and LFinalStream.cp for Final builds.

Included with the Advanced stationary is an “Utilities” folder with some source code. I have renamed the folder to “Hsoi’s Utilities” since he wrote these sources and I haven’t changed them much. These implement new and delete using some of the PowerPlant features. I also added the access path to HackedPlant, where I’ve placed some modified PowerPlant source files. Comments about what changed and why are included in these files. If you are going to use these changes in all your projects, it might be worthwhile using a Source Tree for the HackedPlant files so that multiple projects can use them.

Once these changes have been made, the difference between these two targets is the setting of two macros and a lot of conditional compilation. The macro NDEBUG should only be defined for the Final target and the macro PP_Debug should be set to 1 for the Debug version and to 0 for the Final version. In order to avoid conditional compilation within the main source files, most of the headers provide macros that depend on the PP_Debug setting. The PowerPlant framework uses macros to avoid cluttering your main code with conditional compilation and I have added the CDebuggingUtilities class in order to remove even more conditionals from the main files. As a warning, I don’t intend to describe how the CDebuggingUtilities methods do what I claim they do. The file is documented with commentary if you are curious.

Four support packages can be used with PowerPlant’s debugging classes: MoreFiles, QC, Spotlight and DebugNew. The standard stationary and this article use only DebugNew and none of the others. If you have these (MoreFiles http://members.aol.com/jumplong/ is free, QC and Spotlight http://www.onyx-tech.com/ are commercial), you can include their source files and libraries and enable support for them in the prefix files.

Adding Some Bugs

The first thing I did to the project was to add some bugs. This involves creating a menu and adding the code to handle the bugs I introduced. The menu can be created in Constructor (the resource editor provided for PowerPlant). The steps involved with Constructor are not that different from any either ResEdit or Resourcerer. To add a menu, you would open the AppResources.ppob file, select the Menus (MENU) item in the window and then created a new menu resource (New Menu Resource in the Edit menu). Unless you want the menu to be titled untitled, you would select the new menu and change its name to Bad Things and its ID number to 1000. You could do this directly in the AppResources.ppob window or you could open an Inspector window from the Window menu. In general, if you select resource IDs above 999 you won’t conflict with any of the PowerPlant resources. Now double-click the menu. This will open the Menu editing window. You would then add new menu items (using New Menu Item in the Edit menu). Next, change the menu names and add command numbers using the tab key (or an Inspector window).

Next you would modify the FindCommandStatus() and ObeyCommand() code to indicate that these should be enabled and to implement the bugs. This was done in the CDocumentApp class and you can view the code to see how extra cases were added to the switch statements in these methods. We will discuss exactly what the code inside each branch does later in this article, suffice it to say these are things you typically would not want your application to do.

Code Changes main.cp

The code changes in the main() function are not specific to this particular PowerPlant application. As a result the code in this project can serve as a template for any other applications you write. Due to space considerations, I’ll only do a quick overview of what the code does here, leaving some topics for later in the article and others unexplored completely. In the source file, the comments from last month’s article is indicated by comments beginning with //1 while the comments which have been introduced for this article is indicated by //•.

main() in main.cp
int main()
{
   (void) set_new_handler(PP_NewHandler);
   
   try
   {
      CDebugUtilities::SetAction();

      SLResetLeaks_();
      DebugNewForgetLeaks_();
      
      InitializeHeap(5);
      UQDGlobals::InitializeToolbox();
      ::FlushEvents(everyEvent, nil);
      UEnvironment::InitEnvironment();

      CDebugUtilities::CheckEnvironment();
   
      LGrowZone* theGrowZone = NEW LGrowZone(20000);
      ValidateObject_(theGrowZone);
      SignalIf_(theGrowZone->MemoryIsLow());

      {
         CDocumentApp   theApp;
         theApp.Run();
      }

      CDebugUtilities::PowerPlantCleanUp();
      DebugNewReportLeaks_();
      CDebugUtilities::ShowLeaks();
      
   }
   catch (...)
   {
      SignalStringLiteral_(“Exception caught in main”);
   }
   
   return 0;
}

The first thing we do is to install our own handler for new. This handler is designed to use other classes in the PowerPlant framework to handle low memory situations. All the CDebugUtilities methods will be inlined no-ops in the Final build, we discuss what they will do in the Debug build. SetAction() will establish the behavior of Throw_ and Signal_ macros (discussed in a later section). SLResetLeaks_() and DebugNewForgetLeaks_() are used in debugging memory (discussed in a later section). After this we call the standard initialization routines for a PowerPlant application, adding a call to CDebugUtilities’ method CheckEnvironment() which confirms that we are running on a system supporting our Debugging Classes.

The LGrowZone class is designed to provide an extra memory cushion when the system has run out of ways to provide us with memory. You should read the comments at the top of the LGrowZone.cp file to take full advantage of the LGrowZone object but for this project we’ll just set aside 20,000 bytes of space. The ValidateObject_ is a memory debugging macro and the call to Signal_ will raise a Signal_ if we could not create the cushion for some reason.

The placement of the CDocumentApp inside its own scope insures that it will be destructed prior to checking for memory leaks. A number of PowerPlant objects are usually not destructed until application termination, but they will show up as leaks while you are debugging. The PowerPlantCleanUp() method will delete all of these objects so that you do not have any phantom leaks showing up in your log files. Finally DebugNewReportLeaks_() will write any leaks found to a log file and ShowLeaks() will open that log file in CodeWarrior if any leaks were found (the code for ShowLeaks() was posted in the PowerPlant newsgroup by David Phillip Oster).

CDocumentApp Changes

There are a few stock changes to the CDocumentApp classes that need to be made. Again, like the changes in the function main(), I won’t describe how they do what I say they do but you can read the documentation in the source file’s commentary.

CDocumentApp() in CDocumentApp.cp
CDocumentApp::CDocumentApp()
{
   if (UEnvironment::HasFeature(env_HasAppearance)) {
      ::RegisterAppearanceClient();
   }
   
   CDebugUtilities::AddSIOUXAttachment(this);
   
   UControlRegistry::RegisterClasses();

   CTextDocument::RegisterClasses();
   
}

We will attach two attachments to the CDocumentApp object in order to aid our debugging. Attachments intercept the ObeyCommand() method and are able to extend the number of commands a LCommander is able to handle. This ability to extend any LCommander’s list of commands without changing the LCommander’s source code is a powerful technique for code reuse and you should read the more complete discussion of attachments in Chapter 15 of The PowerPlant Book or in the March 1999 MacTech article by John C. Daub.

The LSIOUXAttachment allows us to use a console window for the streams cout and cerr. Although I have found that it sometimes interferes with the program, you may find it useful and so I have given an example of its use here. This should only be used in the Debug builds and so I created a CDebugUtilities method to be called in the CDocumentApp’s constructor to handle the conditional compilation.

The other new code here is a call to UControlRegistry::RegisterClasses(). This call is needed to prepare for the dialogs that the debugging classes will use. We will discuss this need for registering classes in the next article. The other place an attachment is added is in the Initialize() method.

Initialize() in CDocumentApp.cp
void
CDocumentApp::Initialize()
{
   LDocApplication::Initialize();

   CDebugUtilities::AddDebugMenuAttachment(this);
}

The first thing to be done is to call Initialize() for the base class of CDocumentApp. This should always be your first call in your Initialize() methods. The LDebugMenuAttachment provides the menu interface to the debugging classes. Since it must be attached after the menu bar has been initialized, it needs to be added in the CDocumentApp’s Initialize() method (not the constructor).

Throw_ and Signal_

The most basic of the debugging tools available are Throw_ and Signal_. The Throw_ macros should be used when a problem occurs that must be handled (for example, if the application runs out of memory). The Signal_ macros should be used when a problem occurs which (while unexpected) should not cause a problem in the final version (for example, if MacsBug is not installed). You can find a number of Throw_ and Signal_ macros in the header file UException.h.

The Debug_Throw macro determines the behavior of Throw_ and the Debug_Signal macro determines the behavior of Signal_. If Debug_Throw is undefined, then Throw_ will cause a C++ exception to be thrown. If Debug_Signal is undefined, then Signal_ will do nothing. On the other hand, if the macros are defined, the behavior of Throw_ and Signal_ depend on a run-time variables of type

type enum {
   debugAction_Nothing,
   debugAction_Alert,
   debugAction_Debugger
} EDebugAction;

The current setting is established by calls to SetDebugThrow_() and SetDebugSignal_(). In the case of debugAction_Nothing, the behavior will be the same as that in the Final build. In the case of debugAction_Alert, an alert will be displayed. Once the alert is displayed you can choose one of the following options: Log, Quiet, Quit, Debugger, Continue. Choosing Log will log the exception to a log file. Choosing Quiet will change the setting to debugAction_Nothing. Choosing Debugger will drop into your debugger (but not change the setting). Choosing Quit will quit the application and choosing Continue will continue execution. In the case of debugAction_Debugger, you will be dropped into the debugger. You can learn a lot about how these work by using the Throw and Signal items in the Bad Things menu while changing the behavior with the gDebugThrow and gDebugSignal items in the Debugging menu (the one whose title is a bug icon). You should also experiment with the StDisableSignal_() and StDisableThrow_() objects which temporarily disable this behavior (examples are available in the Bad Things menu).

Debug New

DebugNew is a collection of routines to help you debug your application for memory errors (leaks, overwriting arrays, dangling pointers). The call to DebugNewForgetLeaks_() in main() tells DebugNew to forget all allocations made prior to that point in the application. The call to DebugNewReportLeaks_() will write out a log file indicating every memory allocation which has not been released up and ShowLeaks() will open this log file if it contains information about any leaks. If you play with the Leak with NEW and Leak with new menu items and then quit the application (while leaving CodeWarrior running), the leaks log should open. In it you can see that by calling NEW you will get the file name and line number where the leaked memory was allocated. The leaks from new are also recorded, but you get no information about where they occur.

The macros DELETE and DELETE_ARRAY can be used in place of delete and delete[] and they will delete the pointer and then set it to nil. All the error handling has been built into the delete operators so you can use them if you prefer. The two DELETE macros replace the DisposeOf_ macros provided by PowerPlant for two reasons: first, most of the error checking was redundant when using PP_DebugNew.cp and second, the non-redundant error checking was incorrectly written.

You should play with the various memory related menu items in this section of the Bad Things menu to get a feel for the type of information DebugNew can provide. One thing I have noticed is that if the pointer is determined to be invalid by DebugNew, its memory will not be reclaimed when you call delete. This means that overwritten arrays or mismatched new/delete calls will add lines to your leaks log. Fixing the overwrite or mismatch problem will fix the leak.

LDebugStream

The LDebugStream class is designed for streaming debug information to a variety of locations. The most common location would be a log file, however, you can also stream to a Throw_, Signal_ or directly to the debugger. If you enable streaming to a console (as I did in this application), you will be able to stream to a console window of your application. The original implementation required conditional compilation in your source code between your Debug build and your Final build. I have removed the need for that by adding no-op implementations in LFinalStream.cp (which is compiled and linked in the Final builds).

The Bad Things menu has a number of items that stream to various locations. You will need to be careful when streaming into a Throw_, Signal_ or to the debugger since these have a limited amount of space to display the information. Streaming to a console has some limitations also. If the console is on the screen, all command-key combinations are sent to the console first (before the CDocumentApp can act on them). In the case of many commands, the console will ignore them and the commands will get lost. You can see this by first streaming to the console and then typing command-N. A new window will not open as long as the console window is the front window.

Given the above limitations, you might guess that most of your streaming will be done to a file and you are probably right. All of the streaming from within the PowerPlant classes is done to a log file that will be placed in the same directory as your application.

Other Debugging Menu Options

That finishes the Bad Things menu, but there are a few items in the Debugging menu which deserve mention. The Command Chain window provides you with a visual representation of the commanders in the application (these were discussed in the previous article). It would be nice if it also listed all the attachments since they affect the command handling but I’ll leave that modification as an exercise for the reader. We will discuss the Visual Hierarchy menu item next week, but if you play around with it, you can probably see figure out what it does. There are a number of Heap Routines for Compacting and Purging the Heap (on command or at regular intervals). These can be useful for stress testing your application. It would be nice to have a similar repeater for DebugNew Validate All, but again, I’ll leave this as an exercise for the reader.

Finally, you can use the Eat Memory… item to determine how your application will handle in low memory situations. One way to do this is to use the Launch Zone Ranger item, check the number of free bytes in the application, round down to the nearest 1000 and then eat that much memory. This should cause the application to put up a low memory warning.

Concluding Remarks

We’re slowly putting together an application that will be able to do something. Although this month’s article seems somewhat off the shortest path, the tools in the Debugging menu will help with some of the topics planned for the third article (windows). A natural question that arises now (if not earlier) is: How much longer until I can really do something? My prediction is after the next three articles (windows, files, dialogs) you should be well on your way. If you can’t wait that long, try reading some of The PowerPlant Book.

PowerPlant References

References that are particularly appropriate for this article are the following:

  • “Applications and Events” chapter in The PowerPlant Book (it has a section on debugging)
  • “Debugging in PowerPlant” chapter in PowerPlant Advanced Topics
  • John C. Daub’s “Modifying Objects at Runtime in PowerPlant” in MacTech, March 1999
  • John C. Daub’s “PowerPlant’s Debugging Classes” in MacTech, May 1999
  • PP_DebugMacros.h, UDebugNew.h, UHeapUtils.h, and UOnyx.h header files.

Aaron teaches in the Mathematics Department at Central Washington University in Ellensburg, WA. Outside of his job, he spends time riding his mountain bike, watching movies and entertaining his wife and two sons. You can email him at montgoaa@cwu.edu, try to catch his attention in the newsgroup comp.sys.mac.oop.powerplant or visit his web site at mac69108.math.cwu.edu:8080/.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Google Earth 7.1.8.3036 - View and contr...
Google Earth gives you a wealth of imagery and geographic information. Explore destinations like Maui and Paris, or browse content from Wikipedia, National Geographic, and more. Google Earth combines... Read more
QuickBooks 16.1.11.1556 R12 - Financial...
QuickBooks helps you manage your business easily and efficiently. Organize your finances all in one place, track money going in and out of your business, and spot areas where you can save. Built for... Read more
FileZilla 3.24.0 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.24.0: New The context menu for remote file search... Read more
Bookends 12.7.8 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more
Duplicate Annihilator 5.8.3 - Find and d...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator detects... Read more
BusyContacts 1.1.6 - Fast, efficient con...
BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more
MarsEdit 3.7.10 - Quick and convenient b...
MarsEdit is a blog editor for OS X that makes editing your blog like writing email, with spell-checking, drafts, multiple windows, and even AppleScript support. It works with with most blog services... Read more
BusyCal 3.1.4 - Powerful calendar app wi...
BusyCal is an award-winning desktop calendar that combines personal productivity features for individuals with powerful calendar sharing capabilities for families and workgroups. Its unique features... Read more
VirtualBox 5.1.14 - x86 virtualization s...
VirtualBox is a family of powerful x86 virtualization products for enterprise as well as home use. Not only is VirtualBox an extremely feature rich, high performance product for enterprise customers... Read more
Bookends 12.7.8 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more

Super Mario Run dashes onto Android in M...
Super Mario Run was one of the biggest mobile launches in 2016 before it was met with a lukewarm response by many. While the game itself plays a treat, it's pretty hard to swallow the steep price for the full game. With that said, Android users... | Read more »
WarFriends Beginner's Guide: How to...
Chillingo's new game, WarFriends, is finally available world wide, and so far it's a refreshing change from common mobile game trends. The game's a mix of tower defense, third person shooter, and collectible card game. There's a lot to unpack here... | Read more »
Super Gridland (Entertainment)
Super Gridland 1.0 Device: iOS Universal Category: Entertainment Price: $1.99, Version: 1.0 (iTunes) Description: Match. Build. Survive. "exquisitely tuned" - Rock Paper Shotgun No in-app purches, and no ads! | Read more »
Red's Kingdom (Games)
Red's Kingdom 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Mad King Mac has kidnapped your father and stolen your golden nut! Solve puzzles and battle goons as you explore and battle your... | Read more »
Turbo League Guide: How to tame the cont...
| Read more »
Fire Emblem: Heroes coming to Google Pla...
Nintendo gave us our first look at Fire Emblem: Heroes, the upcoming mobile Fire Emblem game the company hinted at last year. Revealed at the Fire Emblem Direct event held today, the game will condense the series' tactical RPG combat into bite-... | Read more »
ReSlice (Music)
ReSlice 1.0 Device: iOS Universal Category: Music Price: $9.99, Version: 1.0 (iTunes) Description: Audio Slice Machine Slice your audio samples with ReSlice and create flexible musical atoms which can be triggered by MIDI notes or... | Read more »
Stickman Surfer rides in with the tide t...
Stickson is back and this time he's taken up yet another extreme sport - surfing. Stickman Surfer is out this Thursday on both iOS and Android, so if you've been following the other Stickman adventures, you might be interested in picking this one... | Read more »
Z-Exemplar (Games)
Z-Exemplar 1.4 Device: iOS Universal Category: Games Price: $3.99, Version: 1.4 (iTunes) Description: | Read more »
5 dastardly difficult roguelikes like th...
Edmund McMillen's popular roguelike creation The Binding of Isaac: Rebirth has finally crawled onto mobile devices. It's a grotesque dual-stick shooter that tosses you into an endless, procedurally generated basement as you, the pitiable Isaac,... | Read more »

Price Scanner via MacPrices.net

Twelve South Releases RelaxedLeather Cases fo...
Inspired by the laid-back luxury of burnished leather boots and crafted in rich tones of taupe, herb and marsala, RelaxedLeather cases deliver smart, easy protection for the iPhone 7. Each genuine... Read more
Week’s Best Deal: New 2016 13-inch 2.0GHz Mac...
Amazon has the new 2016 13″ 2.0GHz non-Touch Bar MacBook Pros on sale for a limited time for $225 off MSRP including free shipping: - 13″ 2.0GHz MacBook Pro, Space Gray (MLL42LL/A): $1274.99 $225 off... Read more
Back in stock: Apple refurbished Mac minis fr...
Apple has Certified Refurbished Mac minis available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz Mac mini: $419 $80 off MSRP - 2.6GHz Mac... Read more
Apple Ranked ‘Most Intimate Brand’
The top ranked ‘”intimate” brands continued to outperform the S&P and Fortune 500 indices in revenue and profit over the past 10 years, according to MBLM’s Brand Intimacy 2017 Report, the largest... Read more
B-Eng introduces SSD Health Check for Mac OS
Fehraltorf, Switzerland based independant Swiss company- B-Eng has announced the release and immediate availability of SSD Health Check 1.0, the company’s new hard drive utility for Mac OS X. As the... Read more
Apple’s Education discount saves up to $300 o...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more
4-core 3.7GHz Mac Pro on sale for $2290, save...
Guitar Center has the 3.7GHz 4-core Mac Pro (MD253LL/A) on sale for $2289.97 including free shipping or free local store pickup (if available). Their price is a $710 savings over standard MSRP for... Read more
128GB Apple iPad Air 2, refurbished, availabl...
Apple has Certified Refurbished 128GB iPad Air 2s WiFis available for $419 including free shipping. That’s an $80 savings over standard MSRP for this model. A standard Apple one-year warranty is... Read more
13-inch 2.7GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 13″ 2.7GHz/128GB Retina Apple MacBook Pro on sale for $100 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro (MF839LL/A): $... Read more
Laptop Market – Flight To Quality? – The ‘Boo...
Preliminary quarterly PC shipments data released by Gartner Inc. last week reveal an interesting disparity between sales performance of major name PC vendors as opposed to that of less well-known... Read more

Jobs Board

*Apple* macOS Systems Integration Administra...
…most exceptional support available in the industry. SCI is seeking an Junior Apple macOS systems integration administrator that will be responsible for providing Read more
*Apple* Retail - Multiple Positions- Deer Pa...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Technician - nfrastructure (United S...
Let’s Work Together Apple Technician This position is based in Portland, ME Life at nfrastructure At nfrastructure, we understand that our success results from our Read more
*Apple* Mobile Master - Best Buy (United Sta...
**467692BR** **Job Title:** Apple Mobile Master **Location Number:** 000602-Columbia MO-Store **Job Description:** **What does a Best Buy Apple Mobile Master Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.