简体   繁体   中英

Finding who has a retain count to an object

I have a UIViewController which has a retainCount of 3 the moment I instantiate it. That stirs me as terribly incorrect. What's the best way of figuring out who bumped up the retainCount to 3? I'd imagine instantiating the object should give the pointer 1, then I suppose maybe pushing it onto the UINavigationController's stack might bump it up one (not sure about that though?), but the third.. is a mystery.

Adam is right that you shouldn't be overly concerned about retain counts.

But if you ever have a legitimate need for solving such a mystery, a good technique is to subclass the affected class just so you can add overrides to the memory-management methods.

Eg in a subclass of UIViewController, you could implement:

- (id) retain
{
    // Break here to see who is retaining me.
    return [super retain];
}

Don't ever rely on retain counts directly. What's happened is that during the initialization process, some piece of code has retain ed and autorelease d the object. Because you can't tell how many times an object has been autorelease d, you don't actually know what the real retain count is.

Retain counts should only be used as a debugging aid, never as program control flow.

As long as you follow all of the rules laid out in the Memory Management Programming Guide for Cocoa , you won't have problems.

What's the best way of figuring out who bumped up the retainCount to 3?

That's approaching the problem from the wrong angle. This will confuse you and will lead you astray (and probably right past) the actual problem, when indeed there is one.

Better to think about who owns the object. Do you intend to keep the object around as the value of one of your own properties? If so, then you are one of its owners. If not, then you aren't. If you pass the object to another object to store in one of its properties, then that other object is also an owner.

These ownerships are just relationships, so it's really easy to keep them straight in your head.

  • “This is one of my controllers. It owns the root objects of my model and one or more view[ controller]s.”
  • “This is a view. It owns some parts of my model.”
  • “This is part of my model. It owns primitive objects only.”
  • “This is another part of my model. It owns some primitive objects and some other bits of model.”

If you have a solid grasp of your ownerships, then you cannot write a memory leak except by forgetting a release or autorelease message (which can happen to anyone), and you will almost certainly not write a cyclic retention (two objects retaining each other) except knowingly and with copious comments and #warnings.

If you haven't worked out your ownerships, then you have probably written one or more memory leaks or cyclic retentions that you don't know about.


Edit: And to answer the actual question, the best way to figure out what has retained—and, possibly, subsequently autoreleased—an object is to use Instruments's Allocations instrument . With it, you can look at the history of any object to see every allocation, retain, autorelease, release, and deallocation of its address.

It's not a 100% solution, but the LLVM Clang Static Analyzer can be a big help in tracking down incorrect manual memory management usage. Between the Static Analyzer and MallocDebug, you can get to be a pro at tracking down memory management issues very quickly. BTW, even though Instruments is the new hotness, I find MallocDebug far more reliable.

You can find the LLVM Clang Static Analyzer here: LLVM/Clang Static Analyzer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM