从可变数组中删除一系列对象时,CFRelease崩溃

时间:2012-04-10 21:32:40

标签: ios memory crash nsmutablearray

我们的一位测试人员报告了以下崩溃:

0 APP_NAME_WAS_HERE 0x00074892 testflight_backtrace + 158
1 APP_NAME_WAS_HERE 0x000754bc TFSignalHandler + 244
2 libsystem_c.dylib 0x378ea7ec _sigtramp + 48
3 CoreFoundation 0x30ef42e6 CFRelease + 94
4 CoreFoundation 0x30f09a36 -[__NSArrayM removeObjectAtIndex:] + 294
5 CoreFoundation 0x30f4a65e -[NSMutableArray removeObjectsInRange:] + 90
6 APP_NAME_WAS_HERE 0x000570ca -[StoryViewController rewindToChunkIndex:] + 558
7 APP_NAME_WAS_HERE 0x00057396 -[StoryViewController restartChapter] + 22

不幸的是,我们无法重现崩溃 - 我们只是通过TestFlight发送崩溃日志。

我们确实收到了调试日志,以确认removeObjectsInRange肯定正在接收正在采取行动的NSMutableArray的有效范围。 (此外,这会引发异常,而不是发出信号,对吗?)

我唯一的想法是该对象正在获得双重释放,但我不确定如何在ARC打开的情况下实现这一目标?

请注意,要删除的对象是UIView个子类,而且之前的部分或全部可能已从其超级视图中删除。如果他们在这个阶段被释放我不会感到惊讶,我只是不明白为什么会导致它崩溃!

编辑:为了验证它是一个过度释放的对象,我人为地尝试过度释放一个对象(使用CFRelease(__bridge (CFTypeRef) obj)强制在ARC环境中释放)来查看它将产生的崩溃日志类型。不幸的是,它有点不同,所以也许它毕竟不是过度释放?它可能是某种涂鸦吗?

以下是明确的过度释放:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x369c732c __pthread_kill + 8
1   libsystem_c.dylib               0x36c20208 pthread_kill + 48
2   libsystem_c.dylib               0x36c19298 abort + 88
3   libsystem_c.dylib               0x36bd437a free + 374
4   libobjc.A.dylib                 0x375e4d72 object_dispose + 14
5   CoreFoundation                  0x362e9618 -[NSObject dealloc] + 76
6   UIKit                           0x310323a8 -[UIView dealloc] + 620
7   libobjc.A.dylib                 0x375e416e _objc_rootRelease + 30
8   CoreFoundation                  0x362dc2e0 CFRelease + 88
9   APP_NAME_WAS_HERE                   0x000cea98 -[StoryViewController rewindToChunkIndex:] (StoryViewController.m:584)

以下是过度发布的崩溃日志:

3 个答案:

答案 0 :(得分:3)

如果查看堆栈跟踪,发生崩溃不是因为索引错误,而是因为对象过度释放。

当您删除对象时添加对象和释放消息时,NSArray会发送保留消息。显然,那个版本正在崩溃。

这意味着,您过度释放了添加到阵列中的对象。

<强>更新

您的子视图是否强烈拥有?您的所有权修饰符是“强”还是“弱”还是unsafe_unretained?即使在ARC中,如果您没有正确“拥有”变量,也可能存在不平衡的调用。例如,由于您手动将视图添加到另一个数组并将其删除,因此您应该“拥有”它。从superview中删除会向视图发送一个版本,addSubview将发送一个retain。当您使用XIB构建视图时,XIB加载机制使用property'w ownership修饰符,并在将其添加到视图(StoryViewController.view)时相应地提高保留计数。由于XIB加载机制将其添加到子视图,因此不应卸载它。如果你想卸载它,你应该通过将子视图(出口)的属性类型更改为“强”来“拥有”它,否则,最终会弄乱所有权。

在编写ARC所有权修饰符时,开始考虑对象图和谁拥有什么。 ARC不像垃圾收集。这样的事情仍然会发生:)

答案 1 :(得分:1)

我对此问题的解决方法是将编译器的优化级别从目标构建设置中的默认设置None [-O0]降低到Fastest, Smallest [-Os](仅在发行版中设置)。

我不确定它是否只是简单地回避问题,或者编译器中是否存在错误,但是你去了。它解释了为什么只有测试人员才能得到它。

答案 2 :(得分:1)

没有看到代码,很难说真正的问题是什么。我打赌这是一个过度释放的案例。请记住,ARC不适用于Core Foundation对象。

您可能已使用便利构造函数而非allocinit分配了属性。此类对象是自动释放的,必须明确保留,否则将在下一个循环中立即取消分配。