Object with a retain count of 3 - iphone

I have a UIView which retain count is three, and I just wanted to know how I can release it so that the retain count is 0?
Thanks in advance.

Did you create it with +alloc or +new, or with a method that has the word "copy" in its name? Did you send it a -retain message? If not, you don't own it and must not release it. And stop looking at the retain count; doing so only serves to over-complicate what is actually a very simple set of rules for memory management.

Never use retain counts to debug. The frameworks do some crazy stuff behind the scenes and can frequently cause your retain counts to be very different from what you think they should be. Release whenever you should and don't worry with it beyond that.
As stated in the official documentation for -retainCount,
Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
Don’t rely on -retainCount. Other objects may be retaining your object without you knowing it, and autoreleased objects might give you a wrong impression of the actual retain count.

[object release];
but the retain count is probably 3 because the view is currently in use. You only need to release it once. Whatever else is using it (like the parent view or an array) will release it when it is no longer needed. Do you perhaps need to remove it from the parent view?

Related

Is there any case where [self retain] is valid?

Reading source code of my current project, I see:
[self retain]
in one class, in its init method.
I don't understand exactly the reason.
Reading memory management rules from Apple, I don't see anything about this, and I don't see any hypothetical [self release].
The object is asserting ownership of itself when it is initialised. The only reason I can see that this might be useful is if the object needs to guarantee its own existence until some event has happened. For example, it might run a timer and then release itself when the timer expires.
If it's not documented and there is no corresponding release, it's probably a bug.
Best guess is that the person writing the code had a retain error and this was a "quick fix" around the real problem.
This seems to be probably an error, usually it's not up to the object to retain himself.
I see only one special case: delegate and notification, where you have to be much more careful about your life cycle, but even if this case, release/retain should not be done in the object itself.
Note to Erick:
In case of UIAlert, you can release it before it has been destroyed because the view has been but in the view hiercarchy, and then referenced. So the view will be automatically destroyed when it will be removed from the view hierarchy
It's not wrong to retain self. But seeing it in an init method sounds suspicious. I can't think of a good example of where that would be a good thing to do. Also though, with ARC, you can't even do that so you'd have to think of a better way of doing things. In general, if an object is required to be alive then there would be another object that is holding onto it. Self retaining objects are prone to errors where they will never be released.
If I recall correctly some classes use the self-retain to avoid pre-mature releasing. I would say it's not exactly best practice, but if you know the rules of the game (in this case Obj-C) you can break them (sometimes).
if you have some object, it's like it have healts/ lives. when you created it , it have one live. and. function 'retain' increasing his number of lives +1, release function decreasing his number of lives -1, dealloc decreasing too, alloc increasing

Memory Leaks in Objective-C / Arrays

I'm looking at someone's code and I know the general rule is if you have alloc/init, you need to release that memory. He uses a lot of NSMutableArrays, alloc/inits them, but does not release them. Can I simply send the autorelease message to the array that gets created if I do not see any other release/autorelease message getting sent to that array? I basically don't want to get his code to crash and stop working either :P.
With NSMutableArrays, when you send the message addObject and the object in that array increases its retain account, if that array gets released, but the object never gets sent a release or removeObject from the array, is that also a memory leak? Thanks.
You need to either -release or -autorelease anything you -retain, +alloc, -copy, +allocWithZone: or -copyWithZone:. (And, if you retain something twice you also need to release it twice.)
When an NSMutableArray (or NSArray, NSSet, or NSDictionary and mutable subclasses) object is dealloc'd (retain count reaches zero), it releases anything it contains. When you add an object to an NSMutableArray, the array retains the object (it does not copy it like some people claim).
I highly recommend the Memory Management Programming Guide to both you and the someone you referred to in the question.
I hope this answer helps you and someone. Good luck. :)
Also, enable the Clang Static Analyser in the build settings. This will tell you at compile time when a leak is going to happen (and much, much more). In fact, it's the first thing I always do when I start a new project. The analyzer never lied to me.
NSArray and NSMutableArray release all of their objects when they are destroyed, so if the array is managed properly with retain and release (or autorelease) the objects within will not be leaked. But if there are arrays that are never released, they will leak, along with everything inside them.
Without seeing the code, it's hard to advocate for just adding autoreleases everywhere, but for arrays that are used only in the context of a single function (and not assigned to ivars or static variables), the answer is yes, they should be autoreleased. Or more idiomatically, create them with methods like +arrayWithCapacity, which returns an object that has already been added to the autorelease pool.
It is general practice to release all the objects you initialize. But in your case, releasing the array should release all objects as well.
But it all depends on how you are using your objects !!!

iphone memory over release

if I release a variable more than it should be, would that be a problem? I cannot determine the retain count ahead of time.
Foreword
The retain count should be considered more of a theoretical offset. You should never care about what the value currently is, just how your actions will offset it. For example, when you add an object to an array, you have offset its retain count by +1, and when you remove an object from an array, you have offset its retain count by −1. When you're completely done with an object, its retain count offset (relative to you) should be 0. What its retain count actually is does not matter, as long as you fulfil your obligations to manage the object appropriately.
Inspecting the retain count explicitly will often not show what you expect. This could be because of optimisations under the hood. Cocoa relies on the developer conforming to the memory management guidelines. Follow these very simple rules, and do not worry about the explicit value of retainCount.
WRT the question
Over-releasing an object (sending it too many release messages) can—and usually does—result in premature deallocation of that object. Any messages that get sent to the address where the deallocated object used to be will usually crash your application. The dumbed-down rules of thumb are:
Sending a alloc, new, retain, copy (or any method with copy in its name) will give you an object with a retain count offset by +1.
Sending release will offset that objects retain count by −1.
Balance each +1 with a −1 and that's it!
Furthermore
If you are developing a framework or library and you are returning objects to users of your framework, don't try to prevent errors in their code by over-retaining objects. Their obligations are exactly the same as yours, and if they break your framework from poor memory management then that is a bug in their code, not yours.
Don't worry about the retainCount. Only send release to an object that you own. If you get an object by sending alloc to a class, or send an object a retain, copy or mutableCopy message, then you own the object and are responsible for sending it a release message at some time in the future.
It's all explained in the Memory Management Guide.
Please please please do not over release an object ever.
While you're developing your app, it's wise to set the environment variable
MallocScribble="YES"
This will immediately overwrite the pointer for a free'd object to 0x555 so you'll crash where you wouldn't before. Also break on obj-c exceptions! These two settings enabled will help make your app more robust.

Any way to check if an instance is still in memory?

Example: I have a view controller and get rid of it. But there's still an variable holding it's memory address. Accessing that results in EXEC_BAD_ACCESS. Of course. But: Is there any way to check if that variable is still valid? i.e. if it's still pointing to something that exists in memory?
You need to read this again:
Cocoa Memory Management Guidelines
In short, if you want something to stick around you must retain it.
If you want something to go away and you have previously retained it, you must release or autorelease it.
You must never call dealloc directly (except [super dealloc]; at the end of every one of your dealloc methods).
You must never release or autorelease an object that you did not retain.
Note that some methods do return retained objects that you must release. If you alloc an instance of a class, that implies a retain. If you copy and instance, the copy is retained.
If you are ever tempted to use the retainCount method, don't. It isn't useful. Only consider retain counts as a delta; if you add, you must subtract, but the absolute value is an implementation detail that should be ignored.
(In other words, even if there were ways to check for an object's validity definitively -- there aren't -- it would be the wrong answer.)
Oh, and use the Build and Analyze feature in Xcode. It does a very good -- but not quite perfect -- job of identifying memory management problems, amongst other things.
That's what the entire memory management model is set up for - if you call retain at the right times, and release and autorelease at the right times, that can't happen. You can use NSZombie to help you debug.
Use "NSZombieEnabled" break point.
For this reason only all strongly recommend us to use accessors. If your object is released anywhere, it will get assigned to nil, and there will be no harm if you call any API or method on Nil object. So please make a habit of using Accessors.
you just add this NSZombieEnabled Flag as an argument to your application in build settings. and enable it. Now you run your application in debug mode. If any such crash is about to occur, this breakpoint will show you which object is freed and where it is crashing.
Cheers,
Manjunath
If by variable, you mean whether the pointer to your object still references valid memory then:
MyClass *myVariable = [[MyClass alloc] init];
//Tons of stuff happens...
if (myVariable != nil)
//Do more stuff

Question about factory method object lifetimes in Objective-C/Cocoa (to retain or not...)

From reading the memory management docs in the SDK, I gathered that factory methods (static constructor methods) would typically be retaining the object for me and adding it to the autorelease pool?
This would mean I have no need to retain & release an object as long as the pool does not get released before I expect? (Which should be at the end of the app, for the default autorelease pool in main()? )
This question: Cocoa Touch Question. Should [NSMutableArray array] be retained? seems to agree with this.
However when I have used the NSMutableArray arrayWithCapacity: method, I've found I have to retain the array or all heck breaks loose.
I'm sure this is all just total n00b-ness, or a bizarre bug elsewhere in the code, but if someone could explain how exactly I may have misunderstood, I'd be much obliged.
Thanks!
Update: Thanks for the answers. I think I've got it now!
From reading the memory management docs in the SDK, I gathered that factory methods (static constructor methods) would typically be retaining the object for me and adding it to the autorelease pool?
Yes, you don't have to worry about releasing objects returned from any method, except the alloc, init, new, and copy methods.
This would mean I have no need to retain & release an object as long as the pool does not get released before I expect?
Yes.
(Which should be at the end of the app, for the default autorelease pool in main()? )
No. You can only count on the object being around until you return from whichever method or function you're in. Typically, autorelease pools are flushed when control returns back to your run loop.
If you want an object instance to survive beyond the current method you must take ownership of it, by calling 'retain'. You are then also responsible for 'releasing' the instance when you no longer need it.
In your case, if you want your NSMutableArray to stick around, you need to retain it. Better yet, use [[NSMutableArray alloc] initWithCapacity: ];
See Practical Memory Management
Usually auto-release pools are drained at the end of the current event loop. A pretty good rule of thumb is that unless you're returning an autoreleased object, if you want that object to remain outside of the current method, you should retain it.
So, when you create your NSMutableArray as an autoreleased object, once your method ends, all bets are off, and that autorelease pool could drain at any time. Retain it, and then release it in your dealloc.
Checkout this diagram below explaining the Application lifecycle. Once the application has launched, your application will be handling various events which could be user generated such as a touch, or a network activity, or one of many events. Once the event has been handled, control returns to the Event Loop that you see below.
This event loop maintains the top level autorelease pool. In pseudocode, this event loop would look something like:
while(wait for event) {
1) create autorelease pool
2) handle event
3) release pool
}
So, whenever a event has been handled, control goes back to the main event loop, and this outer pool will be released. You should retain all objects that were created using convenience methods and will be needed even after the event handling finishes. With the extra retain count, you take ownership of the object and are responsible for releasing it when no longer needed.
iPhone Application http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Art/app_life_cycle.jpg
As soon as you add your object to the array, there is an implicit call to retain for this object, which means once added to the array you can release it from the source, and when you'll call the remove method from the array there will also be an implicit call to release.