5

I'm trying to debug some ARC code, and it'd be really helpful if i could find out when an object of a certain class is added to the autorelease pool (not when it is actually autoreleased down the track).

Is this possible, eg with a breakpoint? Or by overwriting the 'autorelease' method and putting a breakpoint in it? Any suggestions?

-- edit --

The problem is that i've got an infrequent crash occurring where a custom subclass of UIView is autoreleased on a background thread, which crashes because UIView's cannot be dealloc'd on a background thread. The trace looks like below:

0    libsystem_kernel.dylib  __pthread_kill + 8
1    libsystem_c.dylib   pthread_kill + 54
2    libsystem_c.dylib   abort + 94
3    libc++abi.dylib     abort_message + 46
4    libc++abi.dylib     default_terminate() + 24
5    libobjc.A.dylib     _objc_terminate + 146
6    libc++abi.dylib     safe_handler_caller(void (*)()) + 76
7    libc++abi.dylib     operator delete(void*)
8    libc++abi.dylib     __cxa_throw + 122
9    libobjc.A.dylib     objc_exception_throw + 94
10   CoreFoundation  +[NSException raise:format:]
11   Foundation  -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 90
12   MYAPP   MySuperclass.m line 156 -[MySuperclass dealloc]
13   MYAPP  MyClass.m line 41 -[MyClass dealloc]
14 ...   libobjc.A.dylib     _objc_rootRelease + 36
15   libobjc.A.dylib     objc_release + 38
16   libobjc.A.dylib     (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 224
17   libobjc.A.dylib     _objc_autoreleasePoolPop + 12
18   CoreFoundation  _CFAutoreleasePoolPop + 18
19   libdispatch.dylib   _dispatch_worker_thread2 + 338
20   libsystem_c.dylib   _pthread_wqthread + 294
Chris
  • 39,719
  • 45
  • 189
  • 235
  • 2
    Could you tell us more about the problem you're trying to debug? Perhaps there's a better way. Note that [you can use the Allocations instrument to examine the call stack of every `retain`, `release`, and `autorelease` message sent to every object, and you can filter by the class of interest.](http://stackoverflow.com/a/14891837/77567) – rob mayoff Oct 24 '13 at 22:38
  • Ok i'll add it to the question – Chris Oct 24 '13 at 22:39
  • I tried to use instruments, but the app crashes immediately when launching via instruments. The crash log says: `Dyld Error Message: Symbol not found: _objc_setProperty_atomic` – Chris Oct 24 '13 at 22:52
  • No worries, I got instruments working on a colleagues computer. – Chris Oct 24 '13 at 23:17

1 Answers1

7

This might not help with your problem, but I think it answers your original question:

You can add a symbolic breakpoint on [NSObject autorelease] and then set a condition to match your class. If your running on a device $r0 should hold the pointer to the receiving object. You need to do some casting to make the condition work: (BOOL)[(id)$r0 isKindOfClass:[NSArray class]] breaks whenever an NSArray is added to the autoreleasepool. Note that everything will be running very slow as the debugger has to break on every autorelease and check the condition.

Add a symbolic breakpoint

enter image description here

enter image description here

Sebastian
  • 7,670
  • 5
  • 38
  • 50
  • Thanks, this looks great! Any idea what the register would be for the receiving object on the simulator? – Chris Oct 24 '13 at 22:57
  • 1
    `$rdi`, @Chris. Greg Parker has [a table with all the architectures](http://www.sealiesoftware.com/blog/archive/2013/09/12/objc_explain_So_you_crashed_in_objc_msgSend_iPhone_5s_Edition.html) – jscs Oct 24 '13 at 23:03
  • I think it might be $eax actually? – Chris Oct 24 '13 at 23:24
  • I get the following error in my console: `error: use of undeclared identifier '$rdi'` – Chris Oct 24 '13 at 23:32
  • If i change it to $eax, i get this: `Couldn't execute expression: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x5de589dc). The process has been returned to the state before expression evaluation. [no Objective-C description available] Stopped due to an error evaluating condition of breakpoint 9.4: "(BOOL)[(id)$eax isKindOfClass:[NSArray class]]" ` – Chris Oct 24 '13 at 23:33
  • I didn't get it to work in the simulator. Maybe the [iOS Debugging Magic Tech Note](https://developer.apple.com/library/ios/technotes/tn2239/_index.html) helps. – Sebastian Oct 24 '13 at 23:34
  • 2
    On a 32-bit x86 architecture, it's `(BOOL)[((id*)$esp)[1] isKindOfClass:[NSArray class]]`. – rob mayoff Oct 24 '13 at 23:42
  • Thanks rob. And once it breaks, to get access to it in the lldb console, this works: `po ((id*)$esp)[1]` – Chris Oct 24 '13 at 23:52
  • FWIW, this technique *does* work, but it's incredibly slow. I think using the instruments trace here might be more usable: `http://stackoverflow.com/a/14891837/77567` – Chris Oct 25 '13 at 00:02