【问题标题】:iPhone SDK mem management issues - EXC_BAD_ACCESSiPhone SDK 内存管理问题 - EXC_BAD_ACCESS
【发布时间】:2010-10-20 17:11:53
【问题描述】:

我已经关注这个问题很长时间了,非常感谢任何帮助或建议。我确定它很简单,但我似乎找不到它。在我的应用程序委托中,我使用以下代码加载了一堆附件对象(我创建的一个支持 NSCopying 的对象):

NSString     *path    = [[NSBundle mainBundle] pathForResource:@"Accessories" ofType:@"plist"];
NSDictionary *accDict = [[NSDictionary alloc] initWithContentsOfFile:path];

self.colors = (NSArray *) [accDict objectForKey:@"Colors"]; 
self.exteriorAccessories = [self loadAccessoriesForMode:EXTERIOR_MODE withDictionary:accDict];
self.interiorAccessories = [self loadAccessoriesForMode:INTERIOR_MODE withDictionary:accDict];
[accDict release];  

这是它调用的方法的定义:

-(NSArray *)loadAccessoriesForMode:(NSString *)mode withDictionary:(NSDictionary *) dictionary
{
    NSMutableArray *tempValues = [[NSMutableArray alloc] init]; 
    for (NSDictionary *value in [dictionary objectForKey:mode])  
    {
        Accessory *accessory = [[Accessory alloc] initWithDictionary:value];
        [tempValues addObject:accessory];
        [accessory release];
    }

    NSArray *returnArray = [[NSArray alloc] initWithArray:tempValues copyItems:YES];
    [tempValues release];
    [returnArray autorelease];

    return returnArray; 
}

当我发布 accDict 时,我收到了一个 EXC_BAD_ACCESS 异常。如果我在循环中取出附件的释放,一切都很好 - 但我正在泄漏附件对象(这对我来说似乎很明显 - 如果我初始化它并分配它,我的工作就是释放它)。

当我在调试器中逐步执行此操作时,我看到 init、copy 和 dealloc 方法都按预期在我的 Accessory 对象上触发。如果您认为有帮助,我也可以发布 Accessory 对象的代码,但我认为问题出在此代码中。

【问题讨论】:

    标签: iphone cocoa-touch crash memory-management


    【解决方案1】:

    我想我已经找到了原因,但我会将其发布在这里,以便其他人可能受益。它与我发布的代码没有任何关系。相反,问题出在 Accessory 对象内部。我是直接设置东西,而不是通过 self 调用 getter。

    所以这个:

    value = [dict objectForKey:@"myKey"];
    

    而不是这个:

    self.value = [dict objectForKey:@"myKey"];
    

    不知何故,这导致我对 NSDictionary 本身产生了不良的副作用(我认为这不是可变的,但似乎我在某种程度上把事情搞砸了)。我发现这一点的唯一方法是使用非常有用的建议that I found on Cocoa With Love

    当我在 XCode 中使用 Print Description 选项时,我能够看到 NSDictionary 以某种方式包含 AccessoryValue 对象 - 我的自定义对象之一不应该存在,因为它只是从一个简单的 plist 加载的。通过将鼠标悬停在对象上以查看其详细信息(当进程在调试器中暂停时)并单击展开为对象详细信息的三角形旁边的小向上/向下箭头,可以在 XCode 中找到打印描述。对于字典,这会将其全部内容转储到控制台。

    【讨论】:

    • 了解属性“值”是如何定义的以及在其访问器方法中发生了什么很重要。那里有保留和发布吗?
    • 是的,value 是具有 (nonatomic, retain) 的属性。所以我的直觉是调用“value =”只是将指针设置为不调用retain,而“self.value =”调用适当的setter方法,从而调用retain。
    【解决方案2】:

    请在前面加上“我对目标 C 一无所知,但是”:

    在我看来,您需要在将附件项目复制到“returnArray”后释放它们,或者可能不指定“copyItems”。

    【讨论】:

      【解决方案3】:

      在您的代码上运行 Clang。这是天赐之物。叮当规则!它将对您的代码进行静态分析,并告诉您可能会泄漏什么。好东西。

      【讨论】:

        【解决方案4】:

        我与 Exc_Bad_Access 问题斗争了一天,终于找到了答案。问题是当我尝试访问存储在 NSDictionary 中的一个对象时,第一次是可以的,但第二次访问该对象变成了 nil,即使字典中的对象计数保持不变。这种奇怪的行为是由于两次释放对象造成的。这是一个例子:

        NSString* nstring=[[[NSString alloc]init]autorelease] [AnNSDictionaryInstance setObject:nstring forKey:0];

        ... [nstring 释放];

        注意到 nstring 被设置为自动释放然后再次释放?它不会立即显示问题单元您尝试第二次阅读字典对象。我希望有一天苹果的开发团队能够在编译时将其标记为违规。

        我希望这篇文章能帮助别人。

        坎贝尔的韦恩

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-03
          • 2011-01-07
          • 2011-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-06
          相关资源
          最近更新 更多