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).
Coming from the world of managed memory, wondering what would be the proper way to clean up objects when using ARC.
For example: if declaring an instance variable in C#, .NET will allow the GC to pick it up once it leaves scope (method/loop body, etc)
What's the proper way to clean-up in Objective-C? Just set the reference/pointer to nil or call dealloc or will ARC detect that no external references are pointing to the instance once execution leaves scope and do the job for you?
ARC means "Automatic Reference Counting" and is just a way to let the compiler add the calls to retain/release/autorelease for you. It's not the same as GC but in most cases, you can consider that objects lifetime is automatically managed for you, like in GC.
If you want more information, you should read LLVM document on ARC
Last note: never call dealloc yourself. dealloc is the object's finalizer which is called once the ObjC runtime determines that the object reference count has reached 0. This method is only meant to be overriden by subclasses. In ARC mode, you generally don't need to do that, except if your object references non-object ivars that need to be finalized once the object itself is finalized.
will ARC detect that no external references are pointing to the
instance once execution leaves scope and do the job for you
Basically, yes, that's exactly what ARC will do. You don't need to clean up objects when you're using ARC; in fact, you can't (it stops you from trying to perform manual memory management).
You might want to consult the relevant discussion in my book:
http://www.apeth.com/iOSBook/ch12.html#_memory_management
It explains what's really happening behind the scenes (how memory is actually managed) and then goes on to describe how ARC shields you from most of it.
Note that (as I explain in the URL referenced above) it mostly isn't done by anything like garbage collection: it's done by inserting invisible explicit memory management throughout your code.
Well, in the past, iOS programmers were responsible for telling the system when they were done using an object that they allocated by sending the object a release message. That was done in accordance with a memory management system known as manual reference counting. As of Xcode 4.2, programmers no longer have to worry about this and can rely on the system to take care of releasing memory as necessary. This is done through a mechanism known as Automatic Reference Counting, or ARC for short. ARC is enabled by default when you compile new applications using Xcode 4.2 or later.
You can also disable ARC, in your Xcode interface, go to your main project (not main.h) your actual Xcode project, and select it, you should see a window in Xcode that displays the settings for your project, there will be one that says 'Objective-C Automatic Reference Counting' and it will be set to 'Yes', deactivate it (to 'No') and you shouldn't worry about the ARC, if you come from the world of data management and memory as you said, but keep in mind that it would be easier to you to keep updated to the iOS new features system, that are easier to the programmer to program, it just makes our life easier.
And now, the 'proper way to clean-up in Xcode' with ARC is with 'alloc' and 'init'.
With ARC in Xcode you do not need to worry for 'cleaning' that's the job of Xcode now, you just need to:
1) Create a variable.
2) Allocate.
3) Initialize.
That's it.
An example here:
int main (int argc, char * argv[])
{
#autoreleasepool {
Variable *myVariable;
// Create an instance of a Variable and initialize it
myVariable = [Variable alloc];
myVariable = [myVariable init];
// Set variable to 4/20
[myVariable setNumerator: 4];
[myVariable setDenominator: 20];
// Display the variable using the print method
NSLog (#"The value of myVariable is:");
[myVariable print];
}
return 0;
}
Just allocate and then initialize, yo do not need to do any thing else.
Keep in mind getters and setters.
I'm using a library that is not ARC compliant from an ARC based project. A function in that library returns a retained UIImage * object. Is there a way to use the __bridge attributes to let ARC know about this so it can manage the retain count of the returned object? I tried:
UIImage *returnedImage;
returnedImage = (__bridge_transfer UIImage *)functionThatReturnsAUIImage();
But it won't allow me to cast the UIImage * to a UIImage *). I also tried:
returnedImage = (UIImage *)(__bridge_transfer void *)functionThatReturnsAUIImage();
Which also didn't work. The compiler suggested __bridge_retained instead of __bridge_transfer, but that I believe would have done the opposite of what I was after (i.e. it would have increased the retain count on the returned UIImage object).
I believe the proper thing to do is to make the C function return an autoreleased object. As best as I can tell, ARC assumes any C function that returns an object will have returned an autoreleased object. I have access to the source for this library, so I can do this, but I was wondering if there was a solution I could employ from the calling side if I wasn't able to modify the library.
It's too bad that the logical bridge modifier isn't working for you.
Two possible approaches leap out at me.
First, while it's not elegant, you could just write your own image release function, for example:
// ImageManualMemoryManagement.h
#import <UIKit/UIKit.h>
int releaseImage(UIImage *img);
and
// ImageManualMemoryManagement.m
#import "ImageManualMemoryManagement.h"
int releaseImage(UIImage *img)
{
[img release];
return 0;
}
In your project's target settings, under Build Phases, double click on this one .m source file under "Compile Sources" and add the non-ARC flag, -fno-objc-arc (to allow you to use the release method).
You now have a function you can call that will reduce the retain count of your UIImage and then all is good in the world again.
Second, the more dramatic solution would be to write your own non-ARC wrapper class around the entire C interface that your image library presents, remedying those few methods that aren't returning items with the correct retain count. But it seems like a lot of work for just one retainCount transgression. But if the library has it's own weaknesses (e.g. you're dealing with a clumsy low-level library), you might kill two birds with one stone.
According to apple's Transitioning to ARC Release Notes, __unsafe_unretained should be used here.
__unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.
Because ARC and MRC (manual reference counting) has different memory management rules, no keyword that has memory management influence works. The only choice is the keyword __unsafe_unretained which has no memory management influence to both ARC and MRC.
I am writing code intended to work both under ARC and under Garbage Collection.
Here's a bit of code that uses Core Foundation as it might be written specifically for ARC:
CFTypeRef ref=CFCopySomething();
// At this point ref has retain count 1.
id obj=(__bridge_transfer id)ref;
// Ref still has retain count 1 but is now managed by ARC.
[obj doSomething];
// ARC will release ref when done.
It seems this is equivalent to:
CFTypeRef ref=CFCopySomething();
// At this point ref has retain count 1.
id obj=(__bridge id)ref;
// Now ref has retain count 2 due to assigning to strong variable under ARC.
CFRelease(ref)
// Now ref has retain count 1.
[obj doSomething];
// ARC will release ref when done.
The benefit of the latter being that the CFRelease call allows the GC to collect the object. But I'm not sure about calling the CFRelease after transferring to ARC with the bridge-casted assignment.
It certainly seems to work. Is this code OK?
Your second code snippet is correct, and indeed is the best way to handle both ARC and GC. You could also use CFMakeCollectable when creating the object, and then have the CFRelease done as follows:
if ([NSGarbageCollector defaultCollector] == NULL) CFRelease(myCFString)
But I like better what you have with just one call that works for both environments.
Nick,
As the CFObjects are not handled by ARC, you may actually want to keep the manually managed code here. ARC is really focused on Cocoa and not Core Foundation. That said, you said the code works but does it leak? Remember ARC code with the wrong compiler flags fails by leaking. In this Apple documentation, they claim that ARC does not manage CF objects: https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html. Hence, I think your __bridge code leaks and await your confirmation or rejection from Instruments' leaks tool.
Andrew
If I release mainPath in following example the program gives an error (because I’m releasing an object with zero counter)
NSString *mainPath = [NSString stringWithFormat:#"%#/Documents/downloadFile.plist",NSHomeDirectory()];
NSLog(#"address is = %#",mainPath);
[mainPath release]; //Program failed here
But the following code works fine.
NSString *aa=#"hiiiii";
[aa release];
Can anyone explain this?
Actually I’m not clear about the pointer concept (give a suitable link to clear it)
Constant NSStrings are a special case. They are allocated statically at compile time and can't be deallocated. You can send release to a constant string as many times as you like, it'll never get deallocated. This is achieved in the current implementation by setting the retain count to INT_MAX which is treated as a special value meaning "don't decrement me on release".
You should read the Cocoa Memory Management Guide or at least the Objective-C Tutorial by Scott Stevenson. (Really. Do it, you’ll save a lot of time in the long run.) The difference is that the first string is autoreleased, you do not own it and should not release it. The second string is special, I think it’s not allocated on the heap at all and the release is essentially a no-op here.
String with format is a convenience method that autoreleases the string so in this case you are likely to be sending a release message to an already deallocated object.
In your second example, you are creating the string statically so retain counts don't apply.
You don't need to release your objects in either of those cases.
As a rule of thumb, if you didn't use init (or initWithFoo:) to create the object, and didn't deliberately use retain to retain the object (plus couple of other rarer cases), you don't need to use release.