Search code examples
iphonememory-managementxcode4retain

Is there a way to "find mystery retains" ...?


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 looked through the big class and eventually found the various things that needed to be released.

This got me thinking: there just has to be some really easy way to "find" all the retains on an object .. am I right?

So, is there a simple way to "find all the retains" on an object? Is there a button in XCode or Instruments that everyone else knows about?

What do you do when you can't find a mystery retain like that?

So in the iOS universe, if anyone knows the "Show where all the retains came from on this object" button -- thanks!

P.S. Note that there is no leak, and this question is totally unrelated to leaks. The object simply "perfectly correctly" wouldn't release.


Later ..

Truly astounding solution by Fabio:

Fabio has provided an astounding solution to this problem. In nine words, here it is:

-(id)retain
    {
    NSLog(@"%@", [NSThread callStackSymbols]);
    return ([super retain]);
    }

That is amazingly useful in many situations and leads to many other useful things. You've probably saved me two man-weeks of work per annum forever, Fabio. Thanks!

BTW if you're just getting to grips with this and struggling with the output, I saw that typically there will be many chunks featuring "UINib instantiateWithOwner:". It looks like those will come first, the significant chunks will follow.


Solution

  • 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.


    Update with the actual code from Joe

    -(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.