Begin main content

iPad gets back to the priorities of the first Macintosh

The first Mac I ever used was a Mac 128, when my Dad brought one home as part of the ground breaking Apple Test Drive promotion. It booted into the Finder quickly even though it used a floppy. It only ran one program at once, so programs (mostly) started and exited quickly and didn't interact. It had a fixed screen size so everyone's experience was the same. There were desk accessories that gave access to limited functionality while applications were running.

Sounds a lot like the iPad (except bigger and black and white - and of course no 3G ;).

Seriously, it's Steve Job's core vision all over again. Steve Jobs didn't want the Apple ][ to have any expandability, it was Steve Wozniak who convinced him (correctly) that computers were still very much a hobbyist device and need expandability. The original Mac wasn't supposed to have upgradeable ram - it was the engineers (Burrell Smith I think) who secretly made the circuit board easily upgradeable.

Only now, the hardware and connectivity reality has caught up with Jobs' reality: hardware is cheap, expendable and compact - and Apple makes the best. Once again another insanely great device is going to change the place computers have in our lives.

07:08 PM, 27 Jan 2010 by Mark Aufflick Permalink | Comments (1)

Debugging release/autorelease issues in Cocoa

So your code crashes with an EXC_BAD_ACCESS in objc_msgSend and there is *none* of your own code in the stack trace. Bummer. Since all we know from objc_msgSend is that it's trying to call a method on an object. Since we got EXC_BAD_ACCESS you can bet your bottom dollar that it's attempting to call a method on a freed pointer, so there's no obvious way of finding out what the object was. We can, though, easily find the method. Read Greg Parker's excellent post So you crashed in objc_msgSend(). For the iPhone simulator on my Mac I need to do this at the gdb prompt to decode the eax register:

(gdb) x/s $ecx
0x980530c4:	 "release"
you can see that the selector in the second argument is "release". Now we're getting somewhere, we know an already freed object is trying to be released. Since there is none of our code in the stack trace it's a fair bet that it's happening when the autorelease pool is releasing.

There are a few tricks in your toolbox for tracking down over-released objects. There's the NSZombieEnabled, NSAutoreleaseFreedObjectCheckEnabled and other environment variables which will give you better logging rather than just crashing.

I've found this is not always reliable (logs from the above builtin debug options showed that the over-release was on an NSCFDate object, when in fact it was an NSNumber). Sometimes you also just want to trace through exactly what is happening with your retain/release/autorelease cycles. That's what we're about to achieve here.

Ok, so you have a unit test that replicates this problem right? I use the excellent GHUnit by Gabriel Handford. If not you'll have to play around a bit to narrow down your problem code. In my case, I wanted to confirm that a particular unit test was failing during the autorelease pool release. Best way is to wrap the offending code in a new autorelease pool. Then it will be freed inside your code, which you will see in the stack trace, and confirm you have found the reason. My unit test now looks like:

(Note that the code examples, embedded in github gists, are not showing up in my RSS feed. I'll fix that later, but for now please read the original post)

Now when I fail with EXC_BAD_ACCESS my stack trace looks like this:

Where line 91 of CJTestCJCard.m is the [pool release] call above. So something is being added to the autorelease pool, and is *also* being fully released, or maybe it's being added to the pool more times than it is being retained. There doesn't seem to be a way to interrogate the contents of the autorelease pool (which is a shame) but we log some really useful info by overriding a few methods, like NSObject's release and autorelease methods, so we can see when things are being added to the pool and when things are being released. This is some funky stuff, but since we're only doing it in our unit test class, not code we're going to release you can sleep soundly at night. Here's how I effected logging in release and autorelease.

Add this to the top of your unit test class, before your current @implementation:

Now in your unit test class @implementation, you can use the setupClass method to effect the method implementation switcharoo:

Now your log will be filled with log lines like:

This can help when tracking down tricky releasing bugs. Note that not all classes seem to comply. For instance I see plenty of log lines for NSCFString, but never any release lines. I assume that NSCFString release implementation is a bit different since it's a toll free bridged object - getting that to log is an exercise left for the reader!

If you're interested in the functions I used above to interact with the runtime, check out the Introduction to The Objective-C Programming Language and Objective-C Runtime Reference. Note that the code above works fine in the iPhone simulator. It should be fine on 64 bit Mac apps, but you may need to diddle the method structs manually in 32 bit Mac apps since they use the legacy Objective-C runtime (which you can read about in the Objective-C 1 Runtime Reference).

Also note it won't work on the iPhone itself, so to save constantly commenting out code, you can wrap the offending code in #if TARGET_IPHONE_SIMULATOR #endif pairs.

08:38 PM, 13 Jan 2010 by Mark Aufflick Permalink | Comments (2)

Wow - twitter has sure killed my blogging

I'm not the first to note this, but my blogging sure has taken a huge hit thanks to Twitter (where you can follow me as @markaufflick). It's been a bit over a month since my last post. Contrast that with the fact that in the more than 6 years I've been writing this blog I've only not blogged in April 2008, March 2009 and December 2009.

And that's a shame - because some things I blurt out on twitter, either technical or personal, could stand more thought and word-smithing than 140 characters allow.

So one of my 2010 resolutions is to blog more - even if I tweet first.

I'm even open to topic suggestions.

11:37 AM, 02 Jan 2010 by Mark Aufflick Permalink | Comments (0)


Blog Categories

software (41)
..cocoa (23)
  ..heads up 'tunes (5)
..ruby (6)
..lisp (4)
..perl (4)
..openacs (1)
mac (21)
embedded (2)
..microprocessor (2)
  ..avr (1)
electronics (3)
design (1)
photography (26) and white (6)
..A day in Sydney (18)
..The Daily Shoot (6)
food (2)
Book Review (2)


Icon of envelope Request notifications

Syndication Feed


Recent Comments

  1. Mark Aufflick: Re: the go/Inbox go/Sent buttons
  2. Unregistered Visitor: How do make a button to jump to folder
  3. Unregistered Visitor: Note I've updated the gist
  4. Unregistered Visitor: umbrello is now an available port on macPorts
  5. Unregistered Visitor: Updated version on Github
  6. Unregistered Visitor: Modification request.
  7. Unregistered Visitor: Accents and labels with spaces
  8. Unregistered Visitor: Mel Kaye - additional info
  9. Unregistered Visitor: mmh
  10. Mark Aufflick: Thank you