I have a problem with retainCount
NSLog(#"%i", [self.albumReceiver retainCount]);
self.albumReceiver = [[[FacebookAlbumsDelegateReceiver alloc] init: self] autorelease];
NSLog(#"%i", [self.albumReceiver retainCount]);
The retain count on the first line is 0 but when it gets to third line is 3.
The property on self.albumReceiver is retain property... But as far as i can see it should be 2 where other later retain count should went to 1 since it was autorelease later.
NSLog(#"%i", [self.albumReceiver retainCount]);
albumReceiver = [[[FacebookAlbumsDelegateReceiver alloc] init: self];
NSLog(#"%i", [self.albumReceiver retainCount]);
the retain count start with 0 and in this case the second retain count print 2....
Can somebody give some idea of how this retain and release work....
I thought without 'self' keyword, it will ignore the setter call is it? But if i put autorelease on the second example, i will have error.
Firstly, the retain count is an implementation detail that you should not be overly concerned with. You should really only care about ownership.
Having said that, the explanation for what you are seeingis as follows:
The retain count on the first line is 0
That's because self.albumReceiver is nil at that point. On real objects, you will never see a retain count of 0 (in the current implementation of Foundation).
when it gets to third line is 3
Normally you would expect the retain count to be 2, +1 for the alloc and +1 for assignment to a retain property. However, the init: method might cause some other object to retain it, so might the setter for the property. Another object observing the property might choose to retain the object too. In short, unless you know the exact implementation of all the methods involved and you know for sure nothing is using KVO on albumReceiver, all you can say about the retain count is that self has ownership of it (NB ownership is not exclusive, other things may also have ownership). This is why you shouldn't pay too much attention to retain counts.
Can somebody give some idea of how this retain and release work
Yes. You need to think in terms of ownership. Certain methods give you an object that you own. These are any method starting with alloc, any method starting with new, any method starting with copy or mutableCopy and -retain. If you receive an object in any other way, you do not own it. That includes receiving them as a return result of a method, ass parameters of a method or as by reference parameters of a method or as global or static variables.
If you own an object, you must relinquish ownership by either releasing or autoreleasing it, or it will leak. If you do not own an object, you must not release or autorelease it.
I find that it is best to think of "you" in the above as meaning "the scope in which the object reference was declared".
Anyway, I recommend you to read Apple's Memory Management Rules for the definitive explanation and not to trust answers here. If you look at the original edit for this answer, you'll see that I got the rules slightly wrong because they have been tightened up since I last read them.
Do not use retainCount. (For situations where it’s appropriate to use it, see this website.) Further reading: blog post by bbum, previous SO thread one, thread two. Also note that retainCount is deprecated in recent SDKs. It’s a good idea to pay attention to the deprecation warnings, and even better idea to turn all warnings into errors.
It is generally a bad idea to pay any attention to the retainCount of an object in Objective-C because it is usually impossible to know which secret parts of the frameworks feel a need to retain the object.
In the case you cite where you are adding the object to the autorelease pool, the autorelease pool will presumably be retaining the object until it comes time to flush the pool (during the runloop). This probably explains why the retain count is higher for the autoreleased object.
Note the use of the words "presumably" and "probably" in the above paragraph. I have no idea if this is actually what is happening inside the Cocoa/Cocoa Touch frameworks. This is the problem with using retainCount, you have no way of knowing what the retain count should be at any moment.
If you retain the object (or create it with a method name that contains alloc, copy, mutableCopy or new), you release it. The frameworks are free to also retain the object and they will release it when they are ready. When the retain count reaches zero it will be dealloced.
Update: Having looked at the GNUStep source code for NSObject and NSAutoreleasePool my possible explanation above probably isn't what is happening. However, I have no way to check for sure because I can't see Apple's implementation of these two objects. Even more reason not to trust retainCount or any inferences from it.
The only rule that really exists in environments with manual memory management is
If you use alloc, copy, mutableCopy, new
release it. Otherwise DON'T. retainCounts don't really work for debugging. See here
Related
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).
I'm importing some older ObjC code, circa 2006, to the latest Xcode. It was written before the era of ARC, and I don't have a strong handle on the previous system. Looking for some advice on how to diagnose these.
Here's an example, one of hundreds...
sym = [ globals addObject:[ [ NCObject alloc ] initWithArray:saved dimension:dimension type:type ] ] ;
The error isn't specific, do I need an autorelease around the entire thing, or one immediately after "type ]"?
I seem to recall that the basic rule is that if I see an inti, I need to autorelease it. Are there other cases I need to think about?
Yes. Autorelease is right. The alloc creates an rc=+1 object. Adding it to the array makes it +2. Autorelease will leave it at +1, which is where you want it. Releasing the globals array eventually will bring it back to 0, which is also desired behavior.
For clarity:
sym = [[NCObject alloc] initWithArray:saved dimension:dimension type:type];
[globals addObject:sym];
[sym autorelease];
Note that release is just as good in this case (a little better because it doesn't leave any autorelease pool work for later). Unless the function returns sym, you can release.
alloc... (any method that starts with alloc), new, copy..., mutableCopy... give you retained objects (thanks to #jlehr for extending the original list).
Collections retain
objects that are contained in them (in your case, globals retains
that NCObject that you create.
You should balance every retain
that you write with a release or autorelease. If you release an object, you can't use it anymore, because if its
retainCount has reached zero, it will be deallocated instantly. An
autoreleased object will live until the nearest autoreleasepool
drain.
In the example that you wrote, you either have to balance an alloc, so you have to either release your NCObject after you've added it to the array (if you release it before that, it will most likely be deallocated), or autorelease it whenever you want.
But I would really recommend you to read Apple's Advanced Memory Management Programming Guide. It's short. And it describes all the rules that you'll need.
What I am doing is to check the retainCount after allocating the obj and after releasing this obj. Like below
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
TestClass *ptr = [[TestClass alloc] init];
NSLog(#"retain count of ptr is %d",[ptr retainCount]);
[ptr release];
NSLog(#"Right after release:::::retain count of ptr is %d",[ptr retainCount]);
}
What is getting after display on the console is
2012-05-11 13:51:09.515 memoryManagement[1807:f803] retain count of ptr is 1
2012-05-11 13:51:09.516 memoryManagement[1807:f803] Right after release:::::retain count of ptr is 1
I don't why the retainCount after releasing is still 1. Should it be 0.
Please advice me on this issue and point out if I have just made a mistake in my code.
The first rule of Cocoa Club is: don't use -retainCount. The second rule of Cocoa Club is don't use -retainCount.
First off, if you think you need it, you almost certainly don't. If you are using it to debug, you are using the wrong tool. If you are using it for application logic, you have a broken design.
Second, if you have to ask a StackOverflow question about it, you definitely don't need it.
Third, it's subtle, unreliable, can do wacky things behind your back, and generally will cause more headaches than you can possibly imagine. I recommend Bill Bumgarner's blog post.
The actual retain count of an object can never be zero, because when it's zero, nothing has a reference to it, and it is deallocated. The memory doesn't actually get cleared, though, and it looks like the internal release code doesn't bother actually decrementing the count.
Further, you're violating memory management rules; you've got an object that you own, which you then release. You're not allowed to interact with that object through that pointer anymore.
Nothing to see here, and don't bother looking at an object's retain count.
You have an even worse problem than using retainCount.
Never send messages to objects you release -- especially if you have some reason to think their retainCount is really 1. Maybe release is written something like this:
-(void) release {
if ([self retainCount] == 1) {
[self dealloc];
}
else {
// reduce the retain count
}
}
In that case, the object is gone. You send the message, and if the object is somehow still living in deallocated memory, it would report a retainCount of 1 -- no one says release needs to decrement it if it's being deallocated (who would know?).
Once you call release -- you promised never to send messages to the object -- if you break your promise, anything can happen.
The Apple docs explain why retainCount is not what you think it might be
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html
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.
The docs also explain whey you sometimes see a giant number instead of what you think the retainCount should be:
For objects that never get released (that is, their release method does nothing), this method should return UINT_MAX.
This has nothing to do with your case though. If you call retain on ptr right after you init, you will likely see the retainCount as 2 and 1 (or N and N-1), but are not guaranteed that this is true. retainCount is more logical than a lot of these answers would have you believe, but it can't be used in the way you want to reliably.
Never use retainCount. It is confusing and never gives you a clear answer. Also, If you are correctly following memory management guidelines, you would never need to use retaincount.
On most occasions, it gives you ambiguous output.
Eg. [NSString stringwithstring:#"apple"] has a garbage value as retaincount like 1124523415 etc.
So, never trust retainCount.
I'm pretty new to Objective-C, as you may gather, and until recently, I hadn't really understood the need for all this AutoRelease malarky. I think that's mostly because I've started Objective-C with ARC, and haven't had any exposure to doing retains and release.
Anyway, my understanding now is that pre-ARC, if you created an object and needed to return a pointer to it as the returning object of the method/function, you would need to autorelease it, because you are unable to do the "[obj release]" after doing "return obj;"
Worrying about retains and releases isn't an issue with ARC. Does this mean that in our own code, there is really point in creating our own autoreleased objects? Ie, doing [[[Class alloc] init] autorelease]? From what I've gathered, we should still setup autorelease pools, but only because other frameworks or libraries may still return autoreleased objects, but we no longer need to explicitly create autoreleased objects ourselves - is this a fair understanding?
Thanks,
Nick
When using ARC, you do not want to do any memory management yourself. Specifically you will not be calling release and auto release because it does it all for you. In fact, the compiler should probably complain if you try to manage memory yourself.
Instead of [[[Class alloc] init] autorelease]; you'll just call [[Class alloc] init];
I recommend reading this blog post for some really good background on ARC and memory management in general.
Well, your understanding is quite correct. With ARC we do not release or autorelease any more. Just have to make sure that we assign nil (or some other reasonable value) to any reference to objects, which we do not need any more. In the worst case we could still constantly consume additional memory but the memory cannot leak any ore.
And yes, we still maintain autorelease pools for the sake of using framework libraries (linked ones) that may not use ARC.
To answer your question between the lines about the purpose of autorelease. This applies to non-ARC project only, of course.
In the good old days Objective-C did not offer any reference counting but its retain counting. Any allocated memory of objects, that are not retained (or have a retain count of 0) is considered free and may soon be claimed and used by other objects.
This means that every object needs to be retained after its allocation, assuming that you want to keep it around. When the object is not used any more then you need to release it. This comes with two risks. Well, alloc does retain it once automatically.
1) You may forget to release an object that is unused. In the worst case you may even loose all references to an object that stays in memory for ever since.
2) You may still refer to an object hat has been released already and then try accessing it which will most likely end in an BAD_EXC exception.
All this can be quite annoying. In order to get rid of some of these obligations for objects that don't stay around very long, the autorelease was invented. For temporary objects only you alloc it (release-count = 1) and autorelease it. That means that the object will be automatically released (retain count reduced by 1) within the next autorelease circle. But the object remains allocated for your method while it is being executed. Typically the reference variable would be a local one.
Sample:
-(void) myMethod{
AClass *someObject = [[[AClass alloc] init] autorelease];
// use the object
// probably hand it to another object if that takes ownership, i.e. add it ot an Array using addObject:
// don't care any more
}
And that not required any more when using ARC.
I have read that objects retain count and that it can be increased when we assigned a second value (or object).
Can anybody give me an idea about the basic conditions where retainCount increases or decreases (without retain , alloc and release)...
Short answer: no.
Slightly longer one:
Actions on your part that are typically expected to modify the retain count are retain, release, autorelease and calling methods whose name contains new or copy. In some instances, however, they might not do so, for good implementation reasons, but do something else instead. And there are many other things you can do, like adding objects to collections, that may modify the retain count in ways that are just not your business.
Do not use or rely on retain counts. They are an implementation detail.
Your concern is to manage your own ownership, which you do via the semantics of the above-mentioned methods. How that affects the retain count beneath the hood is something you are better off not even looking at.
Please just don't.
Being concerned about retain count is almost always a way to cause bugs, not cure them.
The retain count of an object is an implementation detail that you shouldn't worry about. You should really only concern yourself with when you gain and lose ownership of an object. Here's why:
+alloc returns an object with a retain count of 1. However, you immediately send it an init message which might give you back a completely different object. For instance
NSString* foo = [[NSString alloc] initWithString: #"foo"];
Gives you an object with a retain count of 1, right? Wrong on current implementations of Cocoa. The string returned by +alloc is immediately released and instead a reference to #"foo" is returned. The retain count of #"foo" is INT_MAX.
Retaining an object increases its retain count, right? Probably, but again sending retain to constant strings has no effect and some singletons have a nul implementation of retain too.
Similarly release usually has an effect on the retain count, but again not necessarily for the same reasons.
Sending copy should give you a new object with a retain count of 1 right? Wrong. Immutable objects can implement copy by sending themselves retain and then returning themselves. In most cases, that will add one to the retain count, but of course with string constants, nothing happens.
If you just think in terms of retaining and releasing ownership all of that stuff I have just said becomes irrelevant implementation details.
retainCount of an object changes in the following cases:
When you create an object(new or
alloc, copy or mutablecopy), it has a
retain count of 1.
When you send an object a retain
message, its retain count is
incremented by 1.
When you send an object a release
message, its retain count is
decremented by 1.
When you send a autorelease message
to an object, its retain count
will be decremented by 1(not
immediately as in case of release but
some time in the future)
You can view this post to get a detailed info on how memory management works in iPhone.