iPhone SDK内存管理问题 - EXC_BAD_ACCESS

时间:2009-04-21 00:48:59

标签: iphone cocoa-touch crash memory-management

我长期以来一直盯着同样的问题,非常感谢任何帮助或建议。我确信这很简单,但我似乎无法找到它。在我的app委托中,我正在使用以下代码加载一堆附件对象(我创建的对象,它支持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例外。如果我在循环中取出附件的发布,一切都很好 - 但是我正在泄漏Accessory对象(这似乎是对我来说 - 如果我初始化它并且我分配它,我的工作是释放它)。

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

4 个答案:

答案 0 :(得分:3)

我想我找到了原因,但我会在这里发布,以便其他人可能受益。它与我发布的代码没有任何关系。相反,问题出在Accessory对象中。我直接设置了东西,而不是通过自我调用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中找到,方法是将鼠标悬停在对象上以查看其详细信息(在调试器中暂停该过程)并单击三角形旁边的向上/向下箭头,这些箭头会扩展为对象详细信息。对于字典,这会将其全部内容转储到控制台。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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

... [nstring release];

请注意nstring设置为autorelease然后再次释放?它会在第二次尝试读取字典对象时立即显示问题。我希望有一天Apple的开发团队能够在编译时将其标记为违规。

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

坎贝尔的韦恩