NSDictionary allKeys 崩溃 - 无法理解崩溃报告情况

Posted

技术标签:

【中文标题】NSDictionary allKeys 崩溃 - 无法理解崩溃报告情况【英文标题】:NSDictionary allKeys crashes - Cannot understand crash report circumstances 【发布时间】:2012-03-24 06:24:16 【问题描述】:

我有以下代码:

- (Item *) getRandomItem 
    if (itemIDs == nil) 
        [self parse];
    
    NSArray * allKeys = [allItems allKeys];
    int seed = arc4random()%[allKeys count];
    return [self getItemByID:[allKeys objectAtIndex:seed]];

它有时会在实时应用上崩溃,但我们无法重现崩溃。我一直在尝试分析报告并了解可能导致崩溃的原因,但我没有成功。我尝试以任何方式篡改 allItems 对象以产生崩溃,都会导致与此处报告的错误不同。

我希望了解在什么情况下会发生以下崩溃:

Hardware Model:      iPhone3,1
Code Type:       ARM (Native)
Parent Process:  launchd [1]
OS Version:      iPhone OS 5.0.1 (9A405)
Report Version:  104
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000010
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3427eb30 _class_isInitialized
1   libobjc.A.dylib                 0x3427e8d6 _class_initialize
2   libobjc.A.dylib                 0x3427e88e prepareForMethodLookup
3   libobjc.A.dylib                 0x3427e76a lookUpMethod
4   libobjc.A.dylib                 0x3427e008 objc_msgSend_uncached
5   CoreFoundation                  0x33f7c020 CFRetain
6   CoreFoundation                  0x33f85bac +[__NSArrayI __new::]
7   CoreFoundation                  0x33f85ac6 -[__NSPlaceholderArray initWithObjects:count:]
8   CoreFoundation                  0x33f85806 +[NSArray arrayWithObjects:count:]
9   CoreFoundation                  0x33fa0e92 -[NSDictionary allKeys]
10  AClockworkBrain                 0x0008f46e -[ItemManager getRandomItem] (ItemManager.m:360)
......

谢谢。

【问题讨论】:

您是否使用ARC?这似乎是与内存相关的错误。 等一下,您是否要向字典中添加原始整数?您正在尝试向内存 0x10 处的对象发送消息,这在您的应用程序中似乎是一个普通整数。 理查德,我们没有使用 ARC。 【参考方案1】:
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3427eb30 _class_isInitialized
1   libobjc.A.dylib                 0x3427e8d6 _class_initialize
2   libobjc.A.dylib                 0x3427e88e prepareForMethodLookup
3   libobjc.A.dylib                 0x3427e76a lookUpMethod
4   libobjc.A.dylib                 0x3427e008 objc_msgSend_uncached
5   CoreFoundation                  0x33f7c020 CFRetain
6   CoreFoundation                  0x33f85bac +[__NSArrayI __new::]
7   CoreFoundation                  0x33f85ac6 -[__NSPlaceholderArray initWithObjects:count:]

此崩溃是过度释放或损坏的特征。具体来说,您的字典中的一个键已被过度释放和/或损坏。特别是,isa 指针现在指向垃圾。

allKeys 尝试创建一个包含所有键的临时数组时,它会尝试保留损坏的对象(通过CFRetain,但将其视为对retain 的调用)。运行时无法将 isa 指针识别为已初始化的类(因为它指向垃圾)并尝试在该“类”上调用 initialize,从而导致崩溃。

现在,损坏的isa 很可能是一个指向可读但垃圾的菜单的值,这会导致运行时深处的几层崩溃。最常见的原因是对象被过度释放,然后某个结构碰巧在同一位置进行了 malloc() 处理,并且该结构恰好有一个指针作为第一个条目,这是结构的一种完全常见的模式。

修复?

首先,运行分析器并修复它抱怨的所有问题。

接下来,检查作为该字典键的对象的所有使用情况。看看你是否能找到可能发生过度释放的地方。

最后,尝试开启僵尸,看看能否重现崩溃。

【讨论】:

bbum 谢谢你这么详细的回复。我不知道所有这些低级信息,但您似乎确实知道。我们会仔细研究这个。再次感谢! 这个崩溃发生在我身上,因为我在与管理对象的线程不同的线程上调用了[myDict allKeys]。正如这个答案所说,它是指向已释放对象的指针。

以上是关于NSDictionary allKeys 崩溃 - 无法理解崩溃报告情况的主要内容,如果未能解决你的问题,请参考以下文章

为啥我得到“[__NSArrayI allKeys]:无法识别的选择器发送到实例”/为啥 NSDictionary 正在转换?

为啥我得到“[__NSArrayI allKeys]:无法识别的选择器发送到实例”/为啥 NSDictionary 正在转换?

循环到未知 JSON 数据时如何在 allKeys 上捕获错误?

如何从 NSDictionary 中获取键和值?

避免在 NSDictionary 中排序

NSDictionary和NSArray打印中文出现乱码的解决方案