如何在实例方法中访问super导致EXC_BAD_ACCESS?

时间:2013-10-16 14:04:24

标签: objective-c pointers memory-management

在实例方法中,我在超类上调用相同的选择器并获得EXC_BAD_ACCESS。我正在使用手动引用计数(不是ARC),这发生在主线程中。静态分析报告没有问题,而不是我认为这意味着一个干净的健康状况。相关代码如下:

CommentListMedia.m(下面的跟踪中的堆栈帧1):

- (void)play {
  if ((comments.isLoading) && (! comments.isLoaded)) 
    playWhenLoaded = YES;
  else [super play]; // <-- EXC_BAD_ACCESS happens here
}

MediaControls.m(下面的跟踪中的堆栈帧2):

- (void)play {
  [media play]; // <-- this calls the code above
  [self notifyWithName:MediaControlsDidPlayNotification];
}

MyApp.m(下面的跟踪中的堆栈框架11):

- (void)sendEvent:(UIEvent *)event {
  [super sendEvent:event]; // <-- this calls the code above
  ...
}

CommentListMedia的超类是SequentialMedia,它没有计入堆栈跟踪,因为异常发生在它到达之前。

不幸的是,我只是在崩溃报告(来自Crashlytics)中看到了这一点,并且我自己无法重现它。令我感到奇怪的是,对类实例的引用必须首先执行播放选择器,但不知何故,当它到达结尾时,对超类的引用是不好的。起初我认为实例可能是自动释放的或者其他东西,但我的印象是在运行循环结束时主线程上发生自动释放,而不是在调用中间的某个随机时间。关于可能导致此问题或如何调试它的任何输入将不胜感激。

主线程上的调用堆栈如下所示:

0   libobjc.A.dylib   objc_msgSend + 5
1   MyApp             -[CommentListMedia play]
2   MyApp             -[MediaControls play]
3   UIKit             -[UIApplication sendAction:to:from:forEvent:] + 90
4   UIKit             -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 30
5   UIKit             -[UIControl sendAction:to:forEvent:] + 44
6   UIKit             -[UIControl _sendActionsForEvents:withEvent:] + 374
7   UIKit             -[UIControl touchesEnded:withEvent:] + 590
8   UIKit             -[UIWindow _sendTouchesForEvent:] + 528
9   UIKit             -[UIWindow sendEvent:] + 832
10  UIKit             -[UIApplication sendEvent:] + 196
11  MyApp             -[MyApp sendEvent:]
12  UIKit             _UIApplicationHandleEventQueue + 7096
13  CoreFoundation    __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
14  CoreFoundation    __CFRunLoopDoSources0 + 206
15  CoreFoundation    __CFRunLoopRun + 622
16  CoreFoundation    CFRunLoopRunSpecific + 522
17  CoreFoundation    CFRunLoopRunInMode + 106
18  GraphicsServices  GSEventRunModal + 138
19  UIKit             UIApplicationMain + 1136
20  MyApp             main

1 个答案:

答案 0 :(得分:1)

0   libobjc.A.dylib   objc_msgSend + 5
1   MyApp             -[CommentListMedia play]

可能-[SequentialMedia play]中崩溃。具体来说,如果该方法返回void并作为方法中的最后一个表达式进行调用,则[optimize]编译器可能会生成尾调用。这将有效地导致方法调用从堆栈中消失。

从崩溃报告中发布寄存器的内容。 $ r0可能非常有启发性(因为它是第一个arg,应该是一个可行的对象)。

此外,如果程序中存在大量并发,则可能是对象正在被辅助线程释放和释放。但是,通常情况下,您会看到不止一种奇怪的崩溃(尽管有时不会,如果您的代码大量使用同步原语 - 并发程序在运行与运行之间的一致性可能非常显着)。