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

Ios 从可变数组中删除一系列对象时CFRelease崩溃,ios,memory,crash,nsmutablearray,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 -[__

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

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

过度释放崩溃日志是这样的:

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

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)
NSArray在添加对象时发送保留消息,在删除对象时发送释放消息。显然,该版本正在崩溃

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

更新

您的子视图是否拥有很强的所有权?您的所有权修饰符是否为“强”或“弱”或“不安全”?即使在ARC中,如果您不正确地“拥有”变量,也会有不平衡的调用需要保留。例如,由于您正在手动将视图添加到另一个数组中并将其删除,因此您应该“拥有”它。“从superview中删除”将向该视图发送发布,而“添加子视图”将发送保留。当您使用XIB构建视图时,XIB加载机制使用属性“w所有权”修饰符,并在将其添加到视图(StoryViewController.view)时相应地增加保留计数。由于XIB加载机制将其添加到子视图中,所以不应该卸载它。如果要卸载它,应该通过将子视图(outlets)的属性类型更改为“strong”来“拥有”它,否则,最终会弄乱所有权


在编写弧所有权修改器时,开始考虑对象图以及谁拥有什么。ARC不像垃圾收集。类似的事情仍然会发生:)

我解决这个问题的方法是将编译器的优化级别从目标构建设置(仅在发行版中设置)中的默认设置
最快、最小[-Os]
降低到
无[-O0]


我不确定这是简单地回避了问题,还是编译器中确实存在bug,但你可以这样做。这也解释了为什么只有测试人员才能得到它。

没有看到代码,很难说真正的问题是什么。我敢打赌这是一个被过度释放的案例。记住,ARC不适用于核心基础对象。
您可能使用方便的构造函数而不是
alloc
init
为属性赋值。这些对象是自动释放的,必须显式保留,否则它们将在下一个周期中立即释放。

这也是我的结论(正如我在最初的帖子中提到的,尽管有点过于简短!)。所以我想真正的问题是:怎么可能用圆弧双重释放一个物体?这很有趣。你能在这里粘贴更多的代码吗?您存储的对象是什么?它是CF对象还是NSObject?它是我刚刚从superview中删除的
UIViews
数组,因此我通过从数组中删除来进行清理(我需要这样做,部分原因是它们的顺序很重要)。这里有太多的相关代码要粘贴,真的,因为视图是应用程序的核心!从理论上讲,ref计数如何在该方向上变得不平衡?可能是多线程问题?然而,我的应用程序中几乎没有多线程…更新了我的答案。我不认为这是一个种族问题。对不起,穆根,我刚刚发现了问题并发布了我的答案。正如你所看到的,这很奇怪!谢谢你勇敢的尝试:-)我认为你没有发现你的问题。您可以为NSObject创建一个类别,并覆盖retain和release以记录每个retain和release。通过这种方式,您可以看到错误的来源。这只是运气,优化器对双重释放的对象绝对不会做任何更改。