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

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

Related

Object with a retain count of 3

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?

Retain count for tableView:cellForRowAtIndexPath:

In Apple's example code, the method tableView:cellForRowAtIndexPath: of a UITableViewDataSource returns a cell with a retain count of 1; it allocs it, but doesn't autorelease it. However, the static analyzer complains that this violates the Cocoa naming conventions, since the method name doesn't start with 'new', etc. The documentation doesn't mention the expected retain count of the cell. What retain count should the cell have? Should I file a bug against the documentation? Thanks.
EDIT: The example code I looked at does autorelease it, and my eye somehow skipped over it. Sorry to waste your time. Thanks for the responses.
Further edit: A bug should probably be filed against Clang if questioners are going to get jumped for using its terminology in a question. :-)
The value of retainCount is not really important (it can go up and down for seemingly unknown reasons). But cells created in tableView:cellForRowAtIndexPath: should be autoreleased. What example code are you looking at?
Which example code? MyTableViewController.m returns either [tableView dequeueReusableCellWithIdentifier:kCellID] or [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease].
If the example code does something different, it's probably wrong. Nearly all methods follow Objective-C naming conventions; the ones that don't tend to be explicitly documented.
Retain count is always at least 1. You won't ever get back an object with a retain count less than that, it would be an ex-object already. Please please please don't draw conclusions from retain counts, or have expectations about them, or even ever look at them. Never never never never never.
There may possibly be dodgy example code here and there that does the wrong thing. Ignore it. Do the right thing and don't fret yourself about the rest.
In fact, DO NOT USE THE retainCount at all. I got so confused and it lead me into the totally wrong direction and I wasted literally days hunting down wrong leaks. It means ABSOLUTELY NOTHING if the count goes up or down! Don't waste a second dealing with it.
It's much better to use the Leak or Zombie tools!
(ps also thanks to walkytalky - as I just see he also answered this one!)
Don't worry about the retain count. You alloc a UITableViewCell in your cellForRowAtIndexPath:, which means you have to release it or you have a memory leak. You can't release it because you have to return the cell, have the table view draw it as a subview, then release it. Therefore you autorelease it to have the autorelease pool release it later. When you return it, it hasn't been released yet, but gets released later by the system (you've simply relinquished ownership of it, which is what you want, because you don't maintain a reference to the cell after it's returned from the function).

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

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.
E.g. 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 retained and autoreleased the object. Because you can't tell how many times an object has been autoreleased, 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

Understanding reference counting with Cocoa and Objective-C

I'm just beginning to have a look at Objective-C and Cocoa with a view to playing with the iPhone SDK. I'm reasonably comfortable with C's malloc and free concept, but Cocoa's references counting scheme has me rather confused. I'm told it's very elegant once you understand it, but I'm just not over the hump yet.
How do release, retain and autorelease work and what are the conventions about their use?
(Or failing that, what did you read which helped you get it?)
Let's start with retain and release; autorelease is really just a special case once you understand the basic concepts.
In Cocoa, each object keeps track of how many times it is being referenced (specifically, the NSObject base class implements this). By calling retain on an object, you are telling it that you want to up its reference count by one. By calling release, you tell the object you are letting go of it, and its reference count is decremented. If, after calling release, the reference count is now zero, then that object's memory is freed by the system.
The basic way this differs from malloc and free is that any given object doesn't need to worry about other parts of the system crashing because you've freed memory they were using. Assuming everyone is playing along and retaining/releasing according to the rules, when one piece of code retains and then releases the object, any other piece of code also referencing the object will be unaffected.
What can sometimes be confusing is knowing the circumstances under which you should call retain and release. My general rule of thumb is that if I want to hang on to an object for some length of time (if it's a member variable in a class, for instance), then I need to make sure the object's reference count knows about me. As described above, an object's reference count is incremented by calling retain. By convention, it is also incremented (set to 1, really) when the object is created with an "init" method. In either of these cases, it is my responsibility to call release on the object when I'm done with it. If I don't, there will be a memory leak.
Example of object creation:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Now for autorelease. Autorelease is used as a convenient (and sometimes necessary) way to tell the system to free this object up after a little while. From a plumbing perspective, when autorelease is called, the current thread's NSAutoreleasePool is alerted of the call. The NSAutoreleasePool now knows that once it gets an opportunity (after the current iteration of the event loop), it can call release on the object. From our perspective as programmers, it takes care of calling release for us, so we don't have to (and in fact, we shouldn't).
What's important to note is that (again, by convention) all object creation class methods return an autoreleased object. For example, in the following example, the variable "s" has a reference count of 1, but after the event loop completes, it will be destroyed.
NSString* s = [NSString stringWithString:#"Hello World"];
If you want to hang onto that string, you'd need to call retain explicitly, and then explicitly release it when you're done.
Consider the following (very contrived) bit of code, and you'll see a situation where autorelease is required:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:#"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
I realize all of this is a bit confusing - at some point, though, it will click. Here are a few references to get you going:
Apple's introduction to memory management.
Cocoa Programming for Mac OS X (4th Edition), by Aaron Hillegas - a very well written book with lots of great examples. It reads like a tutorial.
If you're truly diving in, you could head to Big Nerd Ranch. This is a training facility run by Aaron Hillegas - the author of the book mentioned above. I attended the Intro to Cocoa course there several years ago, and it was a great way to learn.
If you understand the process of retain/release then there are two golden rules that are "duh" obvious to established Cocoa programmers, but unfortunately are rarely spelled out this clearly for newcomers.
If a function which returns an object has alloc, create or copy in its name then the object is yours. You must call [object release] when you are finished with it. Or CFRelease(object), if it's a Core-Foundation object.
If it does NOT have one of these words in its name then the object belongs to someone else. You must call [object retain] if you wish to keep the object after the end of your function.
You would be well served to also follow this convention in functions you create yourself.
(Nitpickers: Yes, there are unfortunately a few API calls that are exceptions to these rules but they are rare).
If you're writing code for the desktop and you can target Mac OS X 10.5, you should at least look into using Objective-C garbage collection. It really will simplify most of your development — that's why Apple put all the effort into creating it in the first place, and making it perform well.
As for the memory management rules when not using GC:
If you create a new object using +alloc/+allocWithZone:, +new, -copy or -mutableCopy or if you -retain an object, you are taking ownership of it and must ensure it is sent -release.
If you receive an object in any other way, you are not the owner of it and should not ensure it is sent -release.
If you want to make sure an object is sent -release you can either send that yourself, or you can send the object -autorelease and the current autorelease pool will send it -release (once per received -autorelease) when the pool is drained.
Typically -autorelease is used as a way of ensuring that objects live for the length of the current event, but are cleaned up afterwards, as there is an autorelease pool that surrounds Cocoa's event processing. In Cocoa, it is far more common to return objects to a caller that are autoreleased than it is to return objets that the caller itself needs to release.
Objective-C uses Reference Counting, which means each Object has a reference count. When an object is created, it has a reference count of "1". Simply speaking, when an object is referred to (ie, stored somewhere), it gets "retained" which means its reference count is increased by one. When an object is no longer needed, it is "released" which means its reference count is decreased by one.
When an object's reference count is 0, the object is freed. This is basic reference counting.
For some languages, references are automatically increased and decreased, but objective-c is not one of those languages. Thus the programmer is responsible for retaining and releasing.
A typical way to write a method is:
id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
The problem of needing to remember to release any acquired resources inside of code is both tedious and error-prone. Objective-C introduces another concept aimed at making this much easier: Autorelease Pools. Autorelease pools are special objects that are installed on each thread. They are a fairly simple class, if you look up NSAutoreleasePool.
When an object gets an "autorelease" message sent to it, the object will look for any autorelease pools sitting on the stack for this current thread. It will add the object to the list as an object to send a "release" message to at some point in the future, which is generally when the pool itself is released.
Taking the code above, you can rewrite it to be shorter and easier to read by saying:
id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
Because the object is autoreleased, we no longer need to explicitly call "release" on it. This is because we know some autorelease pool will do it for us later.
Hopefully this helps. The Wikipedia article is pretty good about reference counting. More information about autorelease pools can be found here. Also note that if you are building for Mac OS X 10.5 and later, you can tell Xcode to build with garbage collection enabled, allowing you to completely ignore retain/release/autorelease.
Joshua (#6591) - The Garbage collection stuff in Mac OS X 10.5 seems pretty cool, but isn't available for the iPhone (or if you want your app to run on pre-10.5 versions of Mac OS X).
Also, if you're writing a library or something that might be reused, using the GC mode locks anyone using the code into also using the GC mode, so as I understand it, anyone trying to write widely reusable code tends to go for managing memory manually.
As ever, when people start trying to re-word the reference material they almost invariably get something wrong or provide an incomplete description.
Apple provides a complete description of Cocoa's memory management system in Memory Management Programming Guide for Cocoa, at the end of which there is a brief but accurate summary of the Memory Management Rules.
I'll not add to the specific of retain/release other than you might want to think about dropping $50 and getting the Hillegass book, but I would strongly suggest getting into using the Instruments tools very early in the development of your application (even your first one!). To do so, Run->Start with performance tools. I'd start with Leaks which is just one of many of the instruments available but will help to show you when you've forgot to release. It's quit daunting how much information you'll be presented with. But check out this tutorial to get up and going fast:
COCOA TUTORIAL: FIXING MEMORY LEAKS WITH INSTRUMENTS
Actually trying to force leaks might be a better way of, in turn, learning how to prevent them! Good luck ;)
Matt Dillard wrote:
return [[s autorelease] release];
Autorelease does not retain the object. Autorelease simply puts it in queue to be released later. You do not want to have a release statement there.
My usual collection of Cocoa memory management articles:
cocoa memory management
There's a free screencast available from the iDeveloperTV Network
Memory Management in Objective-C
NilObject's answer is a good start. Here's some supplemental info pertaining to manual memory management (required on the iPhone).
If you personally alloc/init an object, it comes with a reference count of 1. You are responsible for cleaning up after it when it's no longer needed, either by calling [foo release] or [foo autorelease]. release cleans it up right away, whereas autorelease adds the object to the autorelease pool, which will automatically release it at a later time.
autorelease is primarily for when you have a method that needs to return the object in question (so you can't manually release it, else you'll be returning a nil object) but you don't want to hold on to it, either.
If you acquire an object where you did not call alloc/init to get it -- for example:
foo = [NSString stringWithString:#"hello"];
but you want to hang on to this object, you need to call [foo retain]. Otherwise, it's possible it will get autoreleased and you'll be holding on to a nil reference (as it would in the above stringWithString example). When you no longer need it, call [foo release].
The answers above give clear restatements of what the documentation says; the problem most new people run into is the undocumented cases. For example:
Autorelease: docs say it will trigger a release "at some point in the future." WHEN?! Basically, you can count on the object being around until you exit your code back into the system event loop. The system MAY release the object any time after the current event cycle. (I think Matt said that, earlier.)
Static strings: NSString *foo = #"bar"; -- do you have to retain or release that? No. How about
-(void)getBar {
return #"bar";
}
...
NSString *foo = [self getBar]; // still no need to retain or release
The Creation Rule: If you created it, you own it, and are expected to release it.
In general, the way new Cocoa programmers get messed up is by not understanding which routines return an object with a retainCount > 0.
Here is a snippet from Very Simple Rules For Memory Management In Cocoa:
Retention Count rules
Within a given block, the use of -copy, -alloc and -retain should equal the use of -release and -autorelease.
Objects created using convenience constructors (e.g. NSString's stringWithString) are considered autoreleased.
Implement a -dealloc method to release the instancevariables you own
The 1st bullet says: if you called alloc (or new fooCopy), you need to call release on that object.
The 2nd bullet says: if you use a convenience constructor and you need the object to hang around (as with an image to be drawn later), you need to retain (and then later release) it.
The 3rd should be self-explanatory.
Lots of good information on cocoadev too:
MemoryManagement
RulesOfThumb
As several people mentioned already, Apple's Intro to Memory Management is by far the best place to start.
One useful link I haven't seen mentioned yet is Practical Memory Management. You'll find it in the middle of Apple's docs if you read through them, but it's worth direct linking. It's a brilliant executive summary of the memory management rules with examples and common mistakes (basically what other answers here are trying to explain, but not as well).