Objective-C Memory Management

Every object that is derived from NSObject has the ability to be managed by retain counting. When an object is created (alloc) the system will allocate memory for the object and set a retain count to 1. The count can be incremented when a new instance of this object exist (assignment for example) and decrement when an object instance is released. Once the retain count is going to zero the object will be destructed and the memory gets freed. This post is about that retain count.

Basis functions

There some basic functions an object has automatically when derived from NSObject
alloc
allocates the necessary memory for a new object and returns it with a reference count of one.
release
Decreases the receiver’s reference count by one.
autorelease
Adds the receiver to the application’s autorelease pool, which will decrease the receiver’s reference count by “1″ (at some point in the future) . Autorelease is much slower than release, so use it wisely.
retain
Increases the receiver’s reference count by one.
copy
Makes a copy of an object, and returns it with retain count of one.

Example 1

Objects you allocate with alloc should be released with release and then grounded to nil.

If you don’t want to release your objects manually you could make the use of an autorelease pool. If you send theautorelease message to an object it will be sent and added to the autorelease pool. At the end of an event loop, this autorelease pools is released by the application object and then all of the objects contained within it are released, too. At the beginning of the next loop, a new pool is created and so on.

Example 2

An autoreleased Object is considered to be valid whithin the scope where it received the autorelease message.

Example 3

When you have a method that creates and returns an object autorelease is quite useful to make sure that an object will be released on time.

Example 4

There are so named convencience constructors which will return autoreleased objects. If you use them and you want to keep them at the end of a method block, you have to sent a retain message. So if you keept in mind to call release or autorelease for each alloc, you know have to complete the rule to : for each alloc and for each retain you have to call release or autorelease.

So we can breakdown the memory management to some rules :

Rule 1 : Retention Count

  1. Within a given block, the use of –copy, –alloc and –retain should be equal the use of –release and –autorelease.
  2. Objects created using convenience cunstructors (e.g. NSString’s strintWithCString) are concideredautoreleased.
  3. Implement a –dealloc method to release the instance variables you own.

Example 1: alloc and release

Example 2: Convenience constructor

Rule 2 : Always use accessor methods

If you are using retain and release on a classes instance variables throughout your code, you are almost certainly doing the wrong thing. Use conistently accessor methods of classes to decrease memory management problems.

Example

Rule 3 : Ownership in collections like NSArray, NSDictionary, NSSet etc.

When you add an object to a collection class the collection retains it. A release message will be sent when the collection it self gets released. To understand this, think of what would you do if you are planning a collection class. You wanted to make sure that no objects you were given to look after disappeared out from under you else where, so you send them a -retain message as they’re passed in. If they’re removed, you have to send a balancing -release message. Same when your collection will be released, any remaining objects in your collection should be sent a -release message during your own -dealloc method.

The following examples are both correct.

Example 1

Example 2

Release and dealloc

The release message will be sent by you or by an autorelease pool. The release method of an object decreases the reference counter by one, and if its zero calls the dealloc method.

Vicious retain circles

Guess we have an object A is retaining object B and object B is retaining object A. Now these objects never reach a zero retain count. Just in that moment the reference count gets to one, they are effectively out of the program. This is called vicious retain circles and it is possible to have very complex retain cirules like that where the minumum count is even higher than one. To avoid this you should always plan your class dependency wisely. Lets take a look on the Cocoa view hierachy. A NSView can have several subviews which have subviews and so on. On the other side a NSView has also a pointer to the superview. Why doesn’t this ends in an vicious retain circle?  Well, NSViews retains their subviews but not their superview.

Further Links

Leave a Reply

Your email address will not be published. Required fields are marked *

*