我长期以来一直盯着同样的问题,非常感谢任何帮助或建议。我确信这很简单,但我似乎无法找到它。在我的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对象的代码,但我认为问题出在这个代码中。
答案 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的开发团队能够在编译时将其标记为违规。
我希望这篇文章可以帮助别人。
坎贝尔的韦恩