Understanding memory management
09/04/2010 § 3 Comments
It is well known that iOS developers deal with memory management everyday, although a lot of them didn’t really get the “reference counting” idea. That is why it is better to talk about ownership instead of counting.
In fact, the memory management concept in iOS is all about an object ownership schema, that is implemented through reference counting. Basically when no one owns an object, that object reference counting reaches 0 and therefore it is deallocated.
As you probably are an iOS developer, you already know that Objective-C provides some methods like alloc, new, retain, copy, release and autorelease to deal with that counting. But the real question here is when to use them.
The rule is to only relinquish the ownership of an object that you own and you don’t need anymore. Obviously, the less memory you use, the better you are doing.
But when do you have ownership over an object? And when do you need to have it?
You have the ownership of an object if you created it, if it was given to you or if you took it.
- By creating the object, I mean that you are the guy who called alloc, new or copy.
- By given to you, I mean that you are the guy who called a method that starts with the words alloc or new.
- By taking it, I mean that you actually called retain on that object.
Now that you know when you have the ownership, you need to know when you need it.
Basically you need the ownership when you need a strong reference. And what is this supposed to mean?
Let’s start defining what a weak reference is: A weak reference is created by storing a pointer to an object without retaining the object.
Suppose that you want to do some stuff with an object that is stored within a foundation collection such as NSArray. In this case you don’t need to take the ownership over it, because it is already retained and you know that it will continue to be like this, because you are inside the scope of a method (other examples are the UITableView datasources and delegates that we use every day, or even notification listeners from NSNotificationCenter).
Now let’s say that you retrieved that very same object and beyond handling it, you are removing it from that array. In this case you need to take the ownership, because that array will relinquish it as soon as that object is removed from it. By taking the ownership (retaining the object) you are creating a strong reference and therefore you still safe.
If you don’t need the ownership, don’t take it (and don’t bother to relinquish it as well).
The last step is to know how to relinquish ownership.
If you don’t need an object that you own anymore, you just have to release it by sending the release message to it. But what if your task is to deliver an object to another? If you release it, it will be what we call a freed object and therefore the first one who use it will crash the app.
This is one of the cases where you probably want to use the autorelease message. By sending an autorelease to an object, you mean that object will be released in the future and that you don’t want to bother when. For the iOS it means that you want the system to release that object when it’s scope reaches the end, and this happens when the Autorelease Pool is drained.
The Application Kit automatically creates a pool at the beginning of an event cycle and releases it at the end, so your code normally does not have to worry about them. However there are some cases that you better pay attention to it.
- You wrote a thread: If you don’t create a NSAutoreleasePool as soon as the thread begins, your memory will leak;
- You wrote a loop that allocates lots of objects. In this case it is a good idea to create an Autorelease Pool that releases it’s objects after each iteration, so that you can reduce memory usage.
- You wrote something that is not based on the Application Kit (this is quite obvious, isn’t it?)
Now that you know how it works, take a moment to do some experiments and share your thoughts.