Debugging iPhone memory releases

Recently helped John debug why a NSString returned from [UITextView text] was invalid after being returned by a method invoked via NSInvocation on a different thread. (There’s a mouthful)

Anyway, I don’t know gdb very well, so some googling around and I found this cocoadev article on debugging autorelease.

It helped a lot! I wanted to jot this down here so I can remember it later myself

First off, I opened the Target’s Executable and set the environment variables MallocStackLoggingNoCompact and MallocStackLogging to YES.

I then set a breakpoint where my app assigns the value to the variable that was being released behind my back so I could get the address of the variable.

I then set another breakpoint where I was trying to access the now-dead object.

I ran the app under the debugger and noted the address of the object. I then continued and once I stopped, I opened the gdb console and executed:

shell malloc_history <PID> <OBJECT_ADDRESS>

where <PID> is the process id of my running application and <OBJECT_ADDRESS> is the address I had jotted down.

The results were:

Call [4] [arg=0]: thread_954720 |0x1 | start | main | UIApplicationMain | -[UIApplication _run] | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __NSThreadPerformPerform | NSPopAutoreleasePool | _CFRelease | malloc_zone_free

Thus verifying that my object had been released by the AutoReleasePool on the main thread, even before the [NSInvocation invoke] running on the other thread had returned. Fun!

Thus, a proper use of retain on the string from UITexTView view, and making sure I was careful to release any previously retained string, solved the problem

The real problem was trying to understand Cocoa memory management, and never, ever assuming an object will live beyond the current method.