davedelong.com

  • home
  • blog
  • downloads
  • portfolio
  • contact
Home

Search










Have a look at my Amazon Wishlist.

davedelong's tweets

  • @JayCarr it's in the prefs, under "Advanced" — 11 hours 25 min ago
  • so that bug i was tracking down all afternoon wasn't actually my bug. silly xib using a wonky encoding :P — 14 hours 50 min ago
  • @alesplin 5 pm Mountain Time, i think — 16 hours 53 min ago
  • @JayCarr not yet... — 17 hours 23 min ago
  • Software Engineering is the "[art of making] software accessible to those who do not know how it works." http://bit.ly/9cNqsF — 23 hours 26 min ago
  •  
  • 1 of 477
  • ››
more

An Objective-C Pitfall

davedelong — Mon, 09/07/2009 - 12:40

I spend a lot of time on stackoverflow.com (perhaps too much time), and one of the things I see a lot in the Objective-C section is questions about memory management.

Memory management is Hard.

I learned to program in BASIC languages (Visual basic, REALbasic, then Java), and I never had to deal with a pointer. (This, in retrospect, is really unfortunate) So when I tried to learn Objective-C in 2004, I got so lost. I would rage against the compiler about why it needed (or didn't need) those dumb asterisks everywhere, or why there were these random ampersands next to variables in function and method calls, and so on and so on. I eventually gave up and went and got into web development, where I really didn't have to deal with pointers. At all.

But I could hear Objective-C calling me. I enjoyed application development a heck of a lot more than I liked web development, and I've been a Mac user ever since I was born (we still have a Lisa in my parents' garage), and I knew that Objective-C and Cocoa were The Way To Go for application development on a Mac. Then, one fall, I took a wonderful class: CS 124

CS 124 taught me from the ground up. We started with gates and muxes and all that fun stuff, then moved up to memory and the stack. When we started moving on from the stack to the heap, I had one of those really rare "aha!" moments, and everything just clicked. I went back to my apartment, dragged out all of my Cocoa sample code that I'd acquired over the years, and started understanding it. Within two weeks, more or less, I was proficient in Objective-C. Everything else was just learning what code was already written for me (I love Cocoa!).

Memory management took a while to pick up, but understanding pointers was immensely useful to understanding ownership. I've heard Malcolm Crawford (an engineer at Apple) describe it like so:

  • Objects are like timeshares. If you want to participate in a timeshare, you have to own part of it. Likewise, if you want to use an object for an unspecified amount of time, you must own the object. Acquiring part of a timeshare is like retaining an object.
  • If you've decided that you don't like your timeshare anymore, you can go to the timeshare office and turn in your ownership deed. This is like release-ing an object. As soon as no one owns any part of a time share anymore, that time share is destroyed and the land is reclaimed to build something new.
  • But it's sometimes not worth the trouble to go to the office to turn in your deed. Luckily, you can just drop it in the mail, and the office will receive it sometime in the future (we really have no idea how good the post office is these days). This is analogous to sending an object the autorelease message. You're releasing the object, but it's not actually processed until some point in the future.

This is all well and good, and part of the key to understanding the retain-release-autorelease model is knowing that each object has a little number associated with it, called a "retain count". The retain count simple indicates how many people own a part of the object. That's it. It doesn't say who owns it, just that someone (or someones) out there cares about it and doesn't want it to go away. The retain message increments the retain count, and the release and autorelease message decrement it. Once the retain count hits zero, the object is deallocated and the memory is reclaimed by the system. Pretty simple.

Retain counting is where a lot of confusion enters in to newcomers to Objective-C.

You should never rely on the retain count. Ever.

Cocoa does a lot of cool stuff for us, and a lot of the cool stuff it does deals intimately with memory management (arrays, dictionaries, etc). We understand that collection objects retain their members, and we assume that they only retain them once. However, there's nothing stopping an array from retaining each object more than once. We don't know. We can probably make a good guess by inspecting the retainCount before and after adding it to an array, but we don't know if that behavior will always be true in every circumstance.

Arrays are a simple case. When we start dealing with view controllers and navigation controllers and application delegates, things get hazier. The objects are retained somehow (because the code in them is executing), but by whom and how often are unknown. True, they can be figured out with some clever debugging techniques.

The point of all of this is that if you rely on retain counts for managing your memory, you've done wrong. You should never, under any circumstance that I can think of, manage your memory based on retain counts. Instead, follow the guidelines on when you should retain and release/autorelease, and you should never have memory issues.

The documentation (as usual), is really succinct on this:

Typically there should be no reason to explicitly ask an object what its retain count is. The result is often misleading, as you may be unaware of what framework objects have retained an object in which you are interested. In debugging memory management issues, you should be concerned only with ensuring that your code adheres to the ownership rules.

It's really not that difficult, people.

  • Add new comment

In Theory

Anonymous — Wed, 11/25/2009 - 21:27

Conceptually reference counting is relativity easy to grasp. I need something I add one to the reference count, when I no longer need it I subtract one. When it reaches zero the things goes away. In my opinion this is a somewhat naive conception. While the rules for dealing with references in Objective-C and the Foundation framework make most of this somewhat clear and easier to manager, it is tedious and error prone.

A curmudgeon or two over 20 years ago decided that the current state of computers was too slow for the current state of mark and sweep garbage collection. People were under the, misguided but correct, impression that reference counting systems were faster than any of the automatic garbage collection approaches available. The answer today does not appear so simple and the same decisions that were made over 20 years ago would not be made again today.

The generational and incremental approaches to automatic garbage collection that exist today make reference counting appear to be an absurd exercise. For most situations automatic garbage collection is no slower and in other situations it is faster (memory is reclaimed in a separate thread when the core application is waiting on user input). Reference counting schemes generally offer no good solution to circular references and in the case of Objective-C no solution at all , weak references are a loaded gun waiting to to off.

I for one am extremely happy that Apple, finally, decided to included an atomic garbage collector in 10.5. I just don't understand what too them so long.

-Will

  • reply
  • home
  • blog
  • downloads
  • portfolio
  • contact