我有一个iPhone应用程序正在获取内存警告,所以我试图在Instruments的帮助下找到泄漏,更有效地使用内存等。除此之外,我正在尝试取出任何自动释放的对象并替换为手动alloc / init / release对象。但是,某些API调用似乎没有“init”版本(请参阅下面的代码)。我承认有一些基本的误解:
如果我'调用'API并返回基本上自动释放的对象,那么这些对象是否会在仪器中显示为泄漏?我似乎在仪器中看到了这种行为。
如果是2,我是否应该忽略是否有'非自动释放'替代方案并且我正在使用我需要的API?另外,如果这个代码被大量调用,我是否应该重新考虑algor?
这是我的应用程序中的一些实用程序代码,它被调用很多。基本上确定两个日期是否有意义“相等”。我已经留下了已注释掉的代码,因此您可以在我的代码库中看到我正在进行的改进类型 - 当我开始手动创建时,此DID会减少随后在“工具”中运行时的内存泄漏 NSDate(和发布)有所帮助。但是,我仍然有我认为泄漏的日期组件对象...但它是一个API调用(对于代码格式化很抱歉,但我似乎无法在SO上改进它):
+ (BOOL)isDayEqualToDay:(NSDate*)date anotherDate:(NSDate*)anotherDate
{
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//NSCalendar *cal;
NSDateComponents *componentsFromDate, *componentsFromAnotherDate;
NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
//cal = [NSCalendar currentCalendar];
componentsFromDate = [cal components:unitFlags fromDate:date];
componentsFromAnotherDate = [cal components:unitFlags fromDate:anotherDate];
BOOL bDatesEqual = ([componentsFromDate year] == [componentsFromAnotherDate year] &&
[componentsFromDate month] == [componentsFromAnotherDate month] &&
[componentsFromDate day] == [componentsFromAnotherDate day]);
[cal release];
return bDatesEqual;
/*
return (
[componentsFromDate year] == [componentsFromAnotherDate year] &&
[componentsFromDate month] == [componentsFromAnotherDate month] &&
[componentsFromDate day] == [componentsFromAnotherDate day]
);*/
}
我认为componentsFromDate和componentsFromAnotherDate显示为泄漏,但只有从NSData API调用(自动释放)返回的对象。不知道我还能做些什么来提高效率,而且我质疑我对如何最好地使用乐器的理解。建议
答案 0 :(得分:4)
自动释放的对象不应该显示为内存泄漏。有时API会在内部泄漏内存。您应该向Apple提交错误报告。像NSCalendar和NSDateComponenets这样的新类尤其令人怀疑。
至于保留与自动释放,一般规则是除非你处于紧密循环中并不重要。在这种情况下,如果紧密循环在没有事件发生的情况下进行了数千次,则意味着您永远不会“清理”自动释放池。
答案 1 :(得分:3)
当使用像GCD之类的东西时,有一个自动释放池,但你无法知道何时(如果有的话)默认的自动释放池被耗尽。如果您确信释放的对象没有释放,请确保您了解正在使用的线程API。如果内存为我提供正确的GCD调用(dispatch_async)为您排序自动释放池,但实际耗尽池可能需要很长时间。另一方面,NSOperations允许您拥有自动释放池。
我已经看到仪器中的内存泄漏检测依赖于10秒的间隔会导致错误的内存泄漏警告,因为在自动释放池耗尽之前会延迟一段时间。因此,请尝试将有问题的代码包装在:
中NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... [your code] ...
[pool drain];
我建议不要尝试用手动版本替换所有自动释放。使用自动释放会在一个位置产生平衡的保留/释放呼叫计数。在我看来,创建一个对象然后立即自动释放它可以防止大量的内存错误。快速,简单。在使用手动释放呼叫时,您将忘记释放内容。进行手动释放时,特别是错误条件很棘手。
自己做一个池可以让你获得更多控制权,在分配密集型工作期间,创建和排空自己的池有时会更有帮助。但是一如既往地尝试和测试,不做任何假设。