20
Feb
2008
 

Cocoa Coding Practice: Old School vs New

by Marcus Zarra

Garbage Collection

This post is in response to a few queries that I have received regarding my last post showing an NSOperation example. One of the questions raised that I will focus on is my -(void)dealloc method in the NSOperation subclass. The questions boiled down to:

Why are you using releases at all. Garbage collection is the future!

and

You should be just doing [self setVar:nil] instead of that [var release], var = nil; crap.

Garbage Collection

Regarding garbage collection–currently I am not using it in any of my production code. seSales is still backwards compatible with Tiger and will remain so for now. iWebBuddy, however, uses the dotMac SDK quite heavily and therefore it cannot use garbage collection since that SDK is not compatible (yet). Even if I were to start using garbage collection tomorrow I would still be writing dealloc methods, adding autorelease to temporary variables, etc.

The reason for this is simple–it makes the code compatible with both garbage collected and non-garbage collected compiles. I can turn gc on and off without having to go through my code and re-adding all of the memory management. Since Apple was wise enough to make all of the memory calls no-ops with gc turned on it does not hurt anything to leave them in! Since I am a former Java developer, I do not trust garbage collection yet. That may and probably will change in the future but for now, I am watching it very closely.

dealloc and releasing objects

For the second question regarding how I handle my dealloc methods. This requires a little bit more explanation but the short answer is — I am used to doing them that way.

For the longer answer, we have to look at what Objective-C is synthesizing my @property(retain) NSURL *targetURL; into. The resulting setter for this property is something very similar to:

- (void)setTargetURL:(NSURL*)url
{
    if (url == targetURL) return;
    [url retain];
    [targetURL release];
    targetURL = url;
}

If that looks familiar to you, it should. We have been writing setter methods like that for years. So when I call [self setTargetURL:nil] from my dealloc method, it is really doing 3 message calls, an assignment and a conditional–as opposed to my normal release code which is:

- (void)dealloc
{
    [targetURL release], targetURL = nil;
    [super dealloc];
}

In my release there is one message and one assignment. So it is shorter and faster. Of course with modern hardware the difference between these two is negligible.

Conclusion

So which way is better? Neither and both. My coding style is born out of years of habit. To change it now for no gain is a waste of energy and risks introducing bugs into my code that would not otherwise be there. If there was something to be gained from changing the way I handle memory or the way I release my objects then I would absolutely relearn it. While the upgrades to Objective-C in Leopard are great, and I use many of them, they do not force me to change my habits with regard to memory management. And that, in my opinion, is a great thing.

Comments

[…] Cocoa Is My Girlfriend wrote an interesting post today on Cocoa Coding Practice: Old School vs NewHere’s a quick excerptSince Apple was wise enough to make all of the memory calls no-ops with gc turned on it does not hurt anything to leave them in!… […]

nevyn says:

If [self setVar:nil] crashes but [var release] doesn’t, you’re doing it wrong. Personally I like using self.var = nil; — frees the memory, nulls the pointer /and/ the syntax is short and sweet.

Also, saying that you saved two message calls in the destructor doing it your way is perhaps the most preoptimization-y thing I’ve ever heard.

mmalc says:

For the longer answer, we have to look at what Objective-C is synthesizing my @property(retain) NSURL *targetURL; into. The resulting setter for this property is something very similar to:

Actually the synthesised code is not similar to that shown. Since you didn’t specify nonatomic (as in, @property(nonatomic , retain) NSURL *targetURL;), there will be a lock in there too. (And a retain/autorelease around the get accessor. So invoking the accessor in dealloc would be unnecessarily expensive.

Ryan says:

On the topic of “garbage collection is the future,” I thought I would add something I found in the iPhone SDK samples today:

“Note: iPhone OS does not support memory management using the garbage collection feature that is in Mac OS X v10.5 and later.”

So apparently if you develop for the iPhone, garbage collection IS NOT the future.

http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action;jsessionid=EF636612C9CC3FAD27E747A0C66866C0.worker7

Matt Long says:

Retracted

I misunderstood the context. Sorry about that. -Matt

gumoz says:

We does not use garbage collection in production code, in fact it is dumb to not release your memory, the garbage collector will not release the memory when you want to get it released. For heavy duty applications GC is not yet an option, and in fact if you want your code to be portable, don’t use GC like for example: porting a class to the iphone. Or maybe porting it to another platform, also it is more difficult to use garbage collector on Core Foundation than standard destruct methods. Garbage Collector is there for neophyte programmers who do not know how to manage memory but have good ideas for new applications, fast prototyping, and heavy leaking applications (written by the neophytes). A good comparison of this kind of discussions search on google (LabView vs C) it is a similar discussion.

for CF reference check:
http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html