每次调用此方法时,我的NSMutableData都在泄漏,我无法弄清楚如何插入它。解码器分配和初始化后,数据的保留计数增加1,我不明白为什么。我在方法结束时遇到了保留计数2并试图释放它会导致应用程序崩溃。
- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
NSMutableData *theData;
NSKeyedUnarchiver *decoder;
theData = [NSData dataWithContentsOfFile:inFile];
decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];
[decoder finishDecoding];
[decoder release];
}
答案 0 :(得分:4)
通常,最好避免生成自动释放的对象。
[本段的大部分修改自this question。]由于您通常(1)无法直接控制其生命周期,因此自动释放的对象可能会持续相当长的时间,并且会不必要地增加您的内存占用量。应用。虽然在桌面上这个可能没有什么后果,但在更受限制的平台上,这可能是一个重要问题。因此,在所有平台上,特别是在更受约束的平台上,强烈建议您不要使用会导致自动释放对象的方法,而是鼓励使用alloc / init模式。
我建议更换一下:
theData = [NSData dataWithContentsOfFile:inFile];
使用:
theData = [[NSData alloc] initWithContentsOfFile:inFile];
然后在方法结束时添加:
[theData release];
这意味着在方法退出之前将释放theData
。
你最终应该:
- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
NSMutableData *theData;
NSKeyedUnarchiver *decoder;
theData = [[NSData alloc] initWithContentsOfFile:inFile];
decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;
[decoder finishDecoding];
[decoder release];
[theData release];
}
这使内存管理语义清晰,并尽快回收内存。
(1)您可以使用自己的本地自动释放池来控制。有关详情,请参阅Apple's Memory Management Programming Guide。
答案 1 :(得分:3)
我建议更换这一行:
venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];
使用:
ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;
这使得decodedList
的内存管理变得清晰。使用访问器方法分配实例变量被认为是最佳实践(init方法除外)。在您当前的实现中,如果您第二次在同一个对象上调用readVenueArchiveFile:
,则将泄漏(如果decodedList
已有值,则会如此)。此外,你可以将复制逻辑放在你的访问器方法中而忘记它,而不是每次分配一个新值时都要记住mutableCopy(假设有一个很好的理由来制作一个可变拷贝?)。
答案 2 :(得分:2)
不要担心保留计数,担心方法内的平衡。假设venueIOList
是一个实例变量,那么您在此方法中所做的事情看起来是正确的。
稍微扩展一下我的答案:unarchiver可能会在取消归档操作期间保留您的数据,然后在数据-autorelease
完成后发送而不是-release
。由于这不是你所做的事情,所以你不必关心。
答案 3 :(得分:1)
与Refcount相关的内存管理启示的最终来源仍然是IMO,来自Stepwise的"Hold Me, Use Me, Free Me"。
答案 4 :(得分:0)
你的代码是正确的;没有内存泄漏。
theData = [NSData dataWithContentsOfFile:inFile];
相当于
theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];
此时,数据的引用计数为1(如果更少,则将其取消分配)。引用计数将在未来的某个时间点由自动释放池自动递减。
decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
解码器对象保持对数据的引用,该引用将其引用计数增加到2。
在方法返回后,自动释放池将此值减少为1.如果在此方法结束时释放Data,引用计数将变为0,对象将被释放,并且当您尝试使用时应用程序将崩溃用它。