向有效对象发送消息时的 EXC_BAD_ACCESS

发布于 2024-12-02 06:07:07 字数 1065 浏览 5 评论 0原文

我的主应用程序控制器调用子控制器来处理特定的屏幕序列。主控制器将自己设置为子控制器中的委托。当子控制器完成其工作时,它会通知委托人。有时,此通知会失败并显示 EXC_BAD_ACCESS。

0)基于gdb,问题出现在objc_msgSend。两个寄存器都有一个非零值。

gdb: 0x3367cc98  <+0016>  ldr   r5, [r4, #8]

1)我尝试过 NSZombiesEnabled 来跟踪问题,但当时无法重现它。 2)我尝试在有问题的命令之前设置断点,但我再次无法重现该问题。

我不知道发生了什么事。

这是委托属性声明(父控制器比子控制器寿命更长):

@property (assign) id<ParentControllerDelegate> delegate

这是有问题的代码:

- (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
}

这是委托端的代码(委托已由 App_Delegate 保留,因为它是主控制器)。

- (void) done: (UIViewController *) caller {
   NSLog(@"Taken back control");// this never displays
   [caller.view removeFromSuperview];
   [caller release];
}

一些额外的信息: 主控制器保留子控制器。 我还修改了主控制器和子控制器中的释放以在调用时进行记录。根据可见日志,在应用程序过程中都不会调用这两个方法。因此消息的接收者和发送者都是有效的对象。

我真的很茫然。期待您的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

且行且努力 2024-12-09 06:07:07

如果 done: 中的 NSLog 调用从未执行过,那只能意味着您没有调用主控制器的 done:。这可能意味着 self.delegate 无效。这些对象可能是有效且活动的,但它们之间的链接 (self.delegate) 不是。请检查一下。 显示 self.delegate 的地址

NSLog(@"%p", self.delegate);

doStuff 的“Done”分支中,在调用 done: 之前 ,并将其与该地址进行比较主控制器的。

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.

梦里梦着梦中梦 2024-12-09 06:07:07

只是一个大胆的猜测,但如果是“偶尔”,则可能是 viewDidLoadviewDidUnload 在收到内存警告后导致 EXC_BAD_ACCESS 。检查父/子控制器中释放/保留/创建的实例变量,尤其是在上述视图加载方法中。

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.

坐在坟头思考人生 2024-12-09 06:07:07

尝试在调用之前执行检查协议和方法,如代码中所示:

- (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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文