Blog Posts

Basic Memory Management

Nobody has written me so far. This was not unexcepted since I just started my blog today. So I will begin with a tutorial for absolute beginners. I will tell how you should use the retain, release and autorelease message of NSObject. These three fundamental commands are the essence of memory management in Cocoa. You should know from reading the Cocoa documentation that every Cocoa class is derived from NSObject, which means that every Cocoa object inherits those three commands. Cocoa memory management is based on a so called retain counter. The retain counter can also be associated with a counter that counts how many other objects or entities are using this one object. An allocated object in memory always has a retain count higher than zero. If you call retain, the count is incremented. If you call release, the count is decremented. If the retain counter is decremented to zero, the object gets deallocated. If you send an autorelease message to the object, you do not deallocate the object immediately, instead you mark the object that it should be released when nobody else is using it anymore. Now, this is all basic knowledge you get from the Cocoa documentation. But how should you use this mechanism to implement proper memory management? Any object that you allocate can be allocated be sending the alloc and init message to it. It looks like this:

NSObject* myObject = [[NSObject alloc] init];

When you call alloc, you practically make room for the object in the application's memory. By calling init, you setup the room, so that when you enter it, you can use is right away. The object you have just created now has a retain count of 1, which practically means that you (the one) is using. If you now send a release message to this object, you tell it that you do not need it anymore. The retain counter gets decremented. Now nobody uses this object anymore and so it gets deallocated. If you now send another message to this object, your application will most-likly crash, because you want to use an object that does not exist anymore. If you don't know if some other code later in the program will use this object, you should set the object pointer to nil.

myObject = nil;

Now you are save. Nothing will happen with that pointer anymore. If you know that some other entity in your program will use your object but the entity that allocated the object doesn't need it anymore, you should send an autorelease message to it. This way, you tell the object, somewhere in the future when no other entity is using the object anymore, that it should be deallocated automatically. What you actually do is giving your object to an Autorelease Pool that will manage the deallocation for you. This is all there is to know what is to be done by the entity that created the object.

Another thing is when you get an object from another entity. You should always assume that it is autoreleased. You do not need to know if other entities are using the object as well. All you need to care about is that YOU will need use this object. You have to tell it by calling retain. This way you make sure that the object is not released while you are using it. Remember, your application will crash is that's case. When you are done with it, tell it by calling release again. Here is an example, what you should do, when you get an object:

- (void) setObject:(NSObject*)object
{
    [object retain];
    [...] do some stuff
    [object release];
}

Remember send a retain when you want to use the object and send a release when you doesn't want to use it anymore. This is exactly what is happing in the example above. "objectAtInstanceVariable is just another name for your object. At first "objectAsInstanceVariable" points to the old object you previously got. You do not need that anymore, so release it. Instead you need the new object, so send it a retain and tell it its new name. When you saved an object and you sent it the retain method you should also make sure, that when your host object is deallocated, that the saved object gets a release message, otherwise your saved object will never get deallocated again. You do that be overwriting the dealloc method.

- (void) dealloc
{
   [objectAsInstanceVariable release];
   [super dealloc];
}

I told you above that any object you create has a retain count of 1. Well this is true, but you also need to know if the object got an autorelease message by Cocoa it self. There are three ways in Cocoa to create an object. I already showed you the first way, by calling alloc and init. This way your object is not autoreleased. The other way may look like this:

[NSString stringWithFormat:@"%d levels", levelNum];

Some Cocoa classes are able to create objects using factory methods. These methods do have a "+" plus sign in front of the method declaration, instead of a "-" minus. These methods are convience methods and create an object for you by sending alloc, init and autorelease to it. Do not release objects that are created using factory methods, because your application may crash at some erratic point in the future. The Autorelease Pool will try to deallocate the object, but it was already deallocated by us. This can not work. The third method is creating an object by copying another one using copy or mutableCopy. This way the new object will be created without sending an autorelease message to it. So you have to make sure to release or autorelease it when you do not need it anymore.

If you have further questions or if you think I am wrong on something, I am happy if you leave a comment.

December 11th, 2008 • Permalink


Most Recent Blog Posts

12/14/2011 - Instacast 1.4.4 Available
12/09/2011 - Instacast among Best Apps 2011
11/24/2011 - Instacast HD 1.0 Recap
11/23/2011 - Instacast HD - A podcast universe in high definition
11/16/2011 - Improving Support
10/13/2011 - Instacast and iCloud