2

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

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)

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

4

3 回答 3

3

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

NSArray 在添加对象时发送保留消息,在删除对象时发送释放消息。显然,该版本正在崩溃。

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

更新

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

当您编写 ARC 所有权修饰符时,开始考虑对象图以及谁拥有什么。ARC 不像垃圾收集。这样的事情还是会发生:)

于 2012-04-12T00:41:25.997 回答
1

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

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

于 2012-04-17T01:03:54.460 回答
1

没有看到代码,很难说出真正的问题是什么。我敢打赌这是一个过度发布的东西。请记住,ARC 不适用于 Core Foundation 对象。

您可能已经使用便捷构造函数而不是使用allocand分配了属性init。此类对象是自动释放的,必须明确保留,否则它们将在下一个循环中立即释放。

于 2012-04-20T04:59:38.167 回答