TweetFollow Us on Twitter

Debugging Retain Count Bugs

Volume Number: 21 (2005)
Issue Number: 4
Column Tag: Programming

Tips From Big Nerd Ranch

by Aaron Hillegass, Chris Campbell, and Marquis Logan

Debugging Retain Count Bugs

At the Big Nerd Ranch, we teach the world's greatest Cocoa programming course (and the greatest Python, PHP, Perl, and PostgreSQL classes). One of the things that makes the course great is the alumni mailing list. We thought it would be a great service to the larger developer community if we shared some of the tips that have appeared on the list. So each month, we are going to cull through the discussion and publish a few pieces of useful wisdom. This month, we are talking about how to debug errors in the use of retain and release.

Hunting down bugs in your use of retain and release can be very difficult. Before delving into all the ways to find them, let's quickly review the lifetime of an object on the heap. The object is allocated (through the +allocWithZone: method which calls the malloc_zone_calloc() function), it is used, and then it is deallocated (through the -dealloc method which calls the malloc_zone_free() function).

Complicating matters is the retain count. A newly allocated object has a retain count of 1. When an object is retained, the retain count is incremented. When it is released, the retain count is decremented. When the retain count goes to zero, the object is deallocated.

This is complicated even further by the autorelease pool. When an object is sent the message autorelease, it adds itself to the current autorelease pool. When the autorelease pool is deallocated, it send the message release to every object in the pool. In a Cocoa application, the autorelease pool is deallocated after each event is handled.

Use release when possible

Here are two similar erroneous methods:

- (void)bad
{
    NSArray *array = [[NSArray alloc] init];
    [array release];
    [array release];
}

- (void)worse
{
    NSArray *array = [[NSArray alloc] init];
    [array release];
    [array autorelease];
}

The first method is run inside a debugger, it will stop on the erroneous line with a BAD_ACCESS error. The second method will cause a BAD_ACCESS only when the autorelease pool is deallocated. In a large program, it may be difficult to back track to where you autoreleased that object. Using release, besides being more efficient, will make your code easier to debug.

Note that this does not mean that you should break conventions: when creating an object to be vended out, it should be autoreleased:

- (NSNumber *)currentPrice
{
    NSNumber *p = [[NSNumber alloc] initWithInt:(whatTheMarketWillBear - 1)];
    [p autorelease];
    return p;
}

Set Pointers to nil after Objects are Released

To make it impossible to send messages to released objects, set the pointer to nil after the object is released:

- (void)fireThem
{
   [employees release];
   employees = nil;
}

Using Zombies

This code (which uses an object after it has been deallocated) often runs without crashing or throwing exceptions:

- (IBAction)stupidAction:(id)sender
{
    NSMutableString *string = [[nameField stringValue] mutableCopy];
    [string release];
    NSMutableString *anotherString = [NSMutableString stringWithFormat:@"I'm new!"];
    NSLog(@"string = %@", string);
}

The new string object is sometimes created in the same place in memory that the old one had occupied. So, when you run this you sometimes see:

string = I'm new!

On the other hand, sometimes the new string isn't created in the same location and the application crashes with a BAD_ACCESS. As you can imagine, hunting down a bug may or may not rear its ugly head can be maddening.

To debug this code, instead of freeing the memory for reuse, turn the objects into zombies. When you try to use a zombie, Cocoa will throw an exception. Thus, you can consistently reproduce this bug. The trick, then, is to tell Foundation and CoreFoundation, that you want to zombify your objects instead of freeing them.

First, you need to use the debug version of the CoreFoundation framework. To do this, select your executable in Xcode, and in the inspector under the General tab, choose "Use the debug suffix when loading frameworks."

Then, under the Arguments tab, set the environment variable NSZombieEnabled to YES and CFZombieLevel to 5:

Now when you send a message to a released object you will get a nice exception like this:

*** Selector 'respondsToSelector:' sent to dealloced instance 0x328840 of class NSMutableString.

(Remember to disable zombies once the bug is found -- you want the objects to be freed, not zombified in a deployed app.)

Putting a breakpoint on exceptions

Now that you have an exception that is thrown consistently, you will need to create a breakpoint in the debugger where the exception gets raised. Before dealing with the debugger, let's review how exceptions get thrown.

The Cocoa libraries check certain conditions, and if the conditions are not met, they raise exceptions. For example, if you ask for the second item in an array that has only one item, an exception will be thrown. Throwing an exception looks like this:

if (x == 13) {
    NSException *badness = [NSException exceptionWithName:@"BadLuckException"
                                                    reason:@"13 is unlucky"
                                                    userInfo:nil];
    [badness raise];
}

Thus, to stop the debugger as soon as an exception is raised, you can add the breakpoint for -[NSException raise] using the breakpoint panel.

Gradually, Cocoa programmers are moving to the new @throw/@catch/@finally form of exceptions stolen from C++ and Java. In this form, you will throw exceptions like this:

    NSException *badness = [NSException exceptionWithName:@"BadLuckException"
                                                   reason:@"13 is unlucky"
                                                   userInfo:nil];
    
    @throw badness;

(To use new-style exceptions, you must pass the -fobjc-exceptions flag to the compiler.)

To detect when an exception is being thrown from within the debugger, you will want to create a breakpoint on objc_exception_throw().

You will want these breakpoints every time you run the debugger. To automatically add these breakpoints anytime you use gdb, create a .gdbinit file in your home directory and include these lines:

fb -[NSException raise]
fb objc_exception_throw()

Those are the four tips for this week:

  • release instead of autorelease when possible
  • After releasing an object, set pointers to it to nil
  • Use zombies to hunt down retain/release problems
  • Add breakpoints to stop on exceptions

We hope they are useful to you, and we will be back next month with a few more.


Aaron Hillegass, Chris Campbell, and Marquis Logan

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Airmail 3.3.2 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL, Outlook.com, Live.com. Airmail was designed... Read more
Numi 3.15.1 - Menu-bar calculator suppor...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
Airmail 3.3.2 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL, Outlook.com, Live.com. Airmail was designed... Read more
Numi 3.15.1 - Menu-bar calculator suppor...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
Backblaze 4.3.0.44 - Online backup servi...
Backblaze is an online backup service designed from the ground-up for the Mac. With unlimited storage available for $5 per month, as well as a free 15-day trial, peace of mind is within reach with... Read more
Numi 3.15 - Menu-bar calculator supports...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
EtreCheck 3.3.3 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
BusyContacts 1.1.8 - 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

Latest Forum Discussions

See All

The best new games we played this week
We were quite busy this week. A bunch of big mobile games launched over the past few days, alongside a few teeny surprises. There're lots of quality games to load your phone with. We've gone and picked out five of our favorites for the week. [... | Read more »
Magikarp Jump beginner's guide
Magikarp Jump is a mystifying little game. Part Tamagotchi, part idle clicker, there's not a whole lot of video game there, per se, but for some reason we can't help coming back to it again and again. Your goal is to train up a little Magikarp to... | Read more »
Goat Simulator PAYDAY (Games)
Goat Simulator PAYDAY 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: ** IMPORTANT - SUPPORTED DEVICES **iPhone 4S, iPad 2, iPod Touch 5 or better Goat Simulator: Payday is the most... | Read more »
GRID Autosport delayed until autumn
Sorry mobile racing fans -- GRID Autosport has been delayed a few months. The game is now expected to launch this fall on iOS. Feral Interactive announced that they wanted more time to work on the game's UI and overall performance before launching... | Read more »
Zombie Gunship Survival Beginner's...
The much anticipated Zombie Gunship Survival is here. In this latest entry in the Zombie Gunship franchise, you're tasked with supporting ground troops and protecting your base from the zombie horde. There's a lot of rich base building fun, and... | Read more »
Mordheim: Warband Skirmish (Games)
Mordheim: Warband Skirmish 1.2.2 Device: iOS Universal Category: Games Price: $3.99, Version: 1.2.2 (iTunes) Description: Explore the ruins of the City of Mordheim, clash with other scavenging warbands and collect Wyrdstone -... | Read more »
Mordheim: Warband Skirmish brings tablet...
Legendary Games has just launched Mordheim: Warband Skirmish, a new turn-based action game for iOS and Android. | Read more »
Magikarp Jump splashes onto Android worl...
If you're tired ofPokémon GObut still want something to satisfy your mobilePokémon fix,Magikarp Jumpmay just do the trick. It's out now on Android devices the world over. While it looks like a simple arcade jumper, there's quite a bit more to it... | Read more »
Purrfectly charming open-world RPG Cat Q...
Cat Quest, an expansive open-world RPG from former Koei-Tecmo developers, got a new gameplay trailer today. The video showcases the combat and exploration features of this feline-themed RPG. Cat puns abound as you travel across a large map in a... | Read more »
Jaipur: A Card Game of Duels (Games)
Jaipur: A Card Game of Duels 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: ** WARNING: iPad 2, iPad Mini 1 & iPhone 4S are NOT compatible. ** *** Special Launch Price for a limited... | Read more »

Price Scanner via MacPrices.net

Memorial Day savings: 13-inch Touch Bar MacBo...
B&H Photo has the 2016 Apple 13″ Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 13″ 2.9GHz/512GB... Read more
Apple refurbished 13-inch MacBook Airs availa...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 13″ 1.6GHz/8GB/128GB MacBook Air: $... Read more
Apple restocks refurbished 11-inch MacBook Ai...
Apple has Certified Refurbished 11″ MacBook Airs (the latest models recently discontinued by Apple), available for up to $170 off original MSRP. An Apple one-year warranty is included with each... Read more
12-inch 1.2GHz Retina MacBooks on sale for up...
B&H has 12″ 1.2GHz Retina MacBooks on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 12″ 1.2GHz Space Gray Retina MacBook: $1449.99 $150 off... Read more
15-inch 2.7GHz Silver Touch Bar MacBook Pro o...
MacMall has the 15-inch 2.7GHz Silver Touch Bar MacBook Pro (MLW82LL/A) on sale for $2569 as part of their Memorial Day sale. Shipping is free. Their price is $230 off MSRP. Read more
Free Tread Wisely Mobile App Endorsed By Fath...
Just in time for the summer driving season, Cooper Tire & Rubber Company has announced the launch of a new Tread Wisely mobile app. Designed to promote tire and vehicle safety among teens and... Read more
Commercial Notebooks And Detachable Tablets W...
Worldwide shipments of personal computing devices (PCDs), comprised of traditional PCs (a combination of desktop, notebook, and workstations) and tablets (slates and detachables), are forecast to... Read more
Best value this Memorial Day weekend: Touch B...
Apple has Certified Refurbished 2016 15″ and 13″ MacBook Pros available for $230 to $420 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2.6GHz... Read more
13-inch MacBook Airs on sale for up to $130 o...
Overstock.com has 13″ MacBook Airs on sale for up to $130 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
2.8GHz Mac mini available for $973 with free...
Adorama has the 2.8GHz Mac mini available for $973, $16 off MSRP, including a free copy of Apple’s 3-Year AppleCare Protection Plan. Shipping is free, and Adorama charges sales tax in NY & NJ... Read more

Jobs Board

*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* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job 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* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.