Reputation: 49364
I have a controller with a delegate.
@interface MyConversionController : NSObject {
id <ConversionDelegate> _delegate;
}
@property (assign) id delegate;
@end
@implementation
@synthesize delegate = _delegate;
@end
I'm getting Unrecognized selector sent to instance 0x36c4a0
errors. I've set a breakpoint on the -(void)setDelegate(id)delegate
method so I can observe objects that are passed into my MyConversionController
class. My setDelegate
method is called twice, the first time is an object at the address 0x36c4a0
that I know conforms to the <ConversionDelegate>
protocol. The second time this method is called another object is passed in that also conforms to the protocol. When the time comes to start calling methods on the delegate the method calls are sent to the first object (0x36c4a0
) which is now some other kind of object (usually a CFString
or __NSFastEnumerationEnumerator
if that makes a difference).
Does anyone know why this could be happening?
After running malloc_history
I see that the first address, the one that's giving me trouble, is allocated and freed a number of times before I get to it. The second object is just allocated once. Under what conditions would the pointers be reused like this?
Upvotes: 0
Views: 136
Reputation: 49364
The problem is that the the delegate was being prematurely deallocated. The reason this was so difficult to debug was that the deallocation occured in code I had written a long time ago, and the program would quit before the issues would occur. Writing the new sliver of code kept the program open for just long enough for other classes to start sending messages to the deallocated object.
Solution: I ran the code with the the Zombie module in Instruments. Wish I had done this a few days ago, I fixed the code within 30 seconds of looking at the output from Instruments.
Upvotes: 0
Reputation: 16139
You might want to use malloc_history to find the callstack of the object at that address. Do the following in the terminal while your process is running:
malloc_history <pid> 0x36c4a0 # insert the address in question for the 2nd arg
You'll also need to enable MallocStackLogging (thanks to Kubi's comment below on this).
This may help you understand where the object at that address is being allocated.
Also, you've marked the delegate as assign, not retain, however, I think this is appropriate for delegates. That said, if it was autoreleased somewhere else, that memory may be being reused.
Are you possibly autoreleasing the delegate and assigning it? Something like:
delegate = [[[ConversionDelegateClass alloc] init] autorelease];
controller.delegate = delegate
If so, the delegate will be released in the next autopool release since nothing is retaining it and that memory location will be available for re-use.
Upvotes: 1