EXC_BAD_ACCESS when messaging a valid object
My main app controller invokes a subcontroller to handle a certain sequence of screens. The main controller sets itself as a delegate in the subcontroller. When the subcontroller is done doing its stuff, it notifies the delegate. Every now and then, this notification fails with EXC_BAD_ACCESS.
0)Based on gdb, the problem occurs in objc_msgSend. Both registers have a non-zero value.
gdb: 0x3367cc98 <+0016> ldr r5, [r4, #8]
1)I've tried NSZombiesEnabled to track the problem, but I couldn't reproduce it then. 2)I've tried setting a breakpoint just before the problematic command, but again I can't reproduce the issue.
I have no clue what's going on.
This is the delegate property declaration (the parent controller outlives the child):
@property (assign) id<ParentControllerDelegate> delegate
This is the problematic code:
- (void) doStuff {
if(mode == Done) {
NSLog(@"Done. Handling back control");//this开发者_运维知识库 is the last log displayed by the console
[self.delegate done: self];
} else {
// some controller code
}
This is the the code on the delegate side (the delegate has been retained by the App_Delegate, as it is the main controller).
- (void) done: (UIViewController *) caller {
NSLog(@"Taken back control");// this never displays
[caller.view removeFromSuperview];
[caller release];
}
Some extra info: The main controller retains the subcontroller. I've also modified the deallocs in both the main and sub controllers to log when it is called. Based on the visible logs, neither is ever called during the course of the application. Hence both the receiver and the sender of the message are valid objects.
I'm really at loss here. Looking forward to your help.
If the NSLog
call in done:
is never performed, that can only mean that you did not call the main controller's done:
. That can mean that self.delegate
is not valid. The objects may be valid and alive, but not the link (self.delegate
) between them. Check that, please. In doStuff
, in the "Done" branch, show the address of self.delegate
with
NSLog(@"%p", self.delegate);
before you call done:
and compare that with the address of the main controller.
Just a wild guess, but if it's "now and then" it's probably viewDidLoad
or viewDidUnload
causing the EXC_BAD_ACCESS
after receiving memory warning. Check your released/retained/created instance variables in your parent/child controller especially in aforementioned view loading methods.
Try to perform check protocol and method before call as in the code:
- (void) doStuff
{
if(mode == Done)
{
NSLog(@"Done. Handling back control");//this is the last log displayed by the console
if ([delegate conformsToProtocol: @protocol(ParentControllerDelegate)])
{
if ([delegate respondsToSelector: @selector(done:)] == YES)
{
[delegate performSelector: @selector(done:) withObject: self];
}
}
}
else
{
// some controller code
精彩评论