drewh
drewh

Reputation: 10167

How to tell when object is sent release message?

I'm working through a somewhat tricky iPhone crash, and it looks like the culprit is an NSString being prematurely released. I've switched on NSZombiesEnabled and can see that the NSString is a zombie at the time of the crash. However, I can't determine when the object is being released/dealloced--I've combed through my code looking for release messages being sent to this object and have set breakpoints at these spots, but they're not being hit.

I assume this may be a threading or autorelease issue given it's intermittent nature, but is there any way to hook into the objective-c runtime via the Xcode debugger to tell the exact point where an object is being released? Or is there a better way to diagnose this issue?

Upvotes: 1

Views: 1230

Answers (5)

Ish
Ish

Reputation: 1895

Another way to do this. Make sure to turn NSZombie on so it reports the memory address of the object that is getting the extra release. Then Run with Performance Tool->Object Allocations. This will bring up instruments. Look at the Console log as provided by Xcode organizer. Once you get the crash lookup the memory address in instruments. You will see the entire history of mallocs/frees on that object, as well as links straight into your code.

Upvotes: 2

Andrew
Andrew

Reputation: 1347

If you can reproduce the crash in the simulator, you may wish to look into using the malloc_history tool. (It has a man-page.) You need to set some environment variables: I normally set them via the "Edit Active Executable" screen in the Arguments pane, and then use the check-boxes there to enable/disable them. Make sure you disable them before debugging on the device; if enabled the program will try to write to /tmp which the sandbox doesn't allow.

I find this tool combined with NSZombie lets me track down alloc/premature-release/access-after-dealloc errors. Once NSZombie reports access to a deallocated object you can use malloc_history to work out when the object was allocated. This normally sets me on the path to working out where the problem is.

Another tool I've found invaluable is clang from the LLVM project. It's still in development, but they regularly produce binaries for MacOS-X that seem pretty stable to me. In particular, it understands the Cocoa memory-management policy. Using it is as simple as:

% cd ${DIRECTORY_CONTAINING_XCODE_PROJECT}
% xcodebuild clean
% scan-build -V xcodebuild

This will do a full build of your project and produce a report listing any obvious errors (including reference-counting screw-ups) that the tool finds.

Upvotes: 5

Martin Clarke
Martin Clarke

Reputation: 5657

I might not be thinking straight, but have you considered adding a release and dealloc onto your class

- (void) release 
{
  NSLog(@"Releasing");
  [super release];
}
- (void) dealloc
{
  NSLog(@"Deallocating");
  [super dealloc];
}

Incorporating Ben Gotow's comment to use an obj-c category, you end up with this:

@interface NSString (release) 
  -(void) release;
@end

@implementation NSString (release)
-(void) release
{
  NSLog(@"NSString Released!");
  [super release];
}
@end

Upvotes: 4

user23743
user23743

Reputation:

you could tell the objc provider of dtrace to trigger your probe whenever -[NSString release] is called, but this will involve a little nasty hackery. NSStrings aren't actually NSStrings but are all subclasses, because of the way the class is implemented as a class cluster. Now, that's not going to get in our way; what will is that NSString doesn't have its own -release :-). You can provide your own in a category, though.

Alternatively, if it's easy for you to tell which instance of NSString is going to break, you could just set a conditional breakpoint on -[NSObject dealloc] with self==myInstance.

Upvotes: 2

Eric Petroelje
Eric Petroelje

Reputation: 60508

Could you implement dealloc() and put a breakpoint in there? Looking at the stack trace from that point should tell you where and how it's being released.

Upvotes: 0

Related Questions