Recently I was repairing someone\'s code. There was a big class that would not dealloc. You\'d have to hit it with 5 or 6 releases to get it to dealloc.
I carefully
You could set a symbolic breakpoint on retain and then set it to the retain method of the custom class. The problem here is that retain is a method on NSObject
so you will get the choice of all objective-c classes when placing the breakpoint.
In this case it would be better to overwrite the retain method of the custom class with a call to super, so it would not do anything but you could then place a breakpoint in it.
To add a breakpoint action double click on the blue marker. Find the breakpoint in the list and press the + button on the right. Then choose Debugger command
and add the GDB command frame 1
in this field, which will show you the caller of the retain. By this you cold log all retains and where they come from. When logging the releases in a similar way you could check what was the extra release.
It is still a bit tedious, but this is the best I can think of.
Have you try using "Build & Analyse" in Xcode?
It's great for getting the bottom of objects not being released.
Instruments can show you the call stack for every malloc, release, and retain for any Obj-C object in your app with no code changes required. It works when you're using ARC, which is not the case for the solution from fabio.
It's really useful for finding those mystery retains - e.g. when an object just won't dealloc when it should.
Here's how:
Easy! (ish)
Instruments and its memory management stuff is your friend. Leaks and Zombies are two of the most valuable tools available. Use them.
Product -> Profile (or Cmd-I)
It is, unfortunately, not easily possible to programmatically determine what "owns" an object, since the idea of "object ownership" is a coding convention (unless you enable garbage collection).
Stack logging is often useful (I usually use a few breakpoints with bt;continue
) but that only tells you the function that called retain, not the "bigger picture" (e.g. you might "transfer ownership" with [ivar2 release]; ivar2 = ivar1; ivar1 = nil;
). Sometimes it's a UIKit leak so you don't have the source code and you really have to go digging.
If it's not a leak, however, call -release
a few times and see where it crashes!
Just guessing... but you may overwrite the retain method of the custom class calling super and throwing a nice NSLog to print the call stack.
-(id) retain {
NSLog(@"%@", [NSThread callStackSymbols]);
return ([super retain]);
}
Another important detail is that [NSThread callStackSymbols] returns a NSArray of NSStrings that can be filtered and used for other purposes. For example in complex and dynamic code, to check if a method properly causes another one to fire.
NOTE:
In an ARC environment you will need to first add the -fno-objc-arc
to compiler flags to allow you to override retain and call super.