3

每次我调用此方法时,我的 NSMutableData 都会泄漏,我无法弄清楚如何插入它。在分配和初始化解码器后,theData 的保留计数增加了 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];
}
4

5 回答 5

4

减少峰值内存占用

一般来说,最好的做法是避免生成自动释放的对象。

[本段大部分内容从这个问题修改。]由于您通常(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 的内存管理编程指南

于 2008-10-06T15:43:36.580 回答
3

我建议替换这一行:

venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

和:

ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;

这使得内存管理decodedList一目了然。使用访问器方法(初始化方法除外)分配实例变量被认为是最佳实践。在您当前的实现中,如果您readVenueArchiveFile:在同一个对象上再次调用,您泄漏(如果decodedList已经有一个值,您将会泄漏)。此外,您可以将复制逻辑放在访问器方法中并忘记它,而不是每次分配新值时都必须记住 mutableCopy(假设无论如何都有充分的理由制作可变副本?)。

于 2008-10-04T03:58:55.287 回答
2

不要担心保留计数,担心方法内的平衡。venueIOList假设是一个实例变量,你在这个方法中所做的看起来是正确的。

稍微扩展我的答案:取消归档程序可能会在取消归档操作期间保留您的数据,然后在-autorelease完成时发送数据而不是-release. 因为那不是做的事情,所以不必关心。

于 2008-10-03T23:08:05.763 回答
1

引用计数相关的内存管理启示的最终来源仍然是,IMO,来自 Stepwise 的“Hold Me, Use Me, Free Me”

于 2008-10-04T03:15:49.993 回答
0

您的代码是正确的;没有内存泄漏。

theData = [NSData dataWithContentsOfFile:inFile];

相当于

theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];

此时 theData 的引用计数为 1(如果更少,它将被释放)。引用计数将在未来某个时候由自动释放池自动递减。

decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

解码器对象保留对 theData 的引用,这会将其引用计数增加到 2。

方法返回后,自动释放池将这个值递减为1。如果你在这个方法结束时释放数据,引用计数将变为0,对象将被释放,当你尝试使用它时你的应用程序会崩溃。

于 2008-10-04T04:34:01.923 回答