1

在实例方法中,我在超类上调用相同的选择器并获得 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
4

1 回答 1

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

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

从您的崩溃报告中发布寄存器的内容。$r0 可以很有启发性(因为它是第一个参数并且应该是一个可行的对象)。

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

于 2013-10-16T16:47:58.300 回答