6

我有一个 iPhone 应用程序收到内存警告,因此我试图在 Instruments 的帮助下找到泄漏、更有效地利用内存等。除其他外,我正在尝试取出任何自动释放的对象并用手动分配/初始化/释放对象替换。但是,某些 API 调用似乎没有“init”版本(参见下面的代码)。我承认有一些基本的误解:

  1. 如果我“调用”API 并取回本质上是自动释放的对象,这些对象会在 Instruments 中显示为泄漏吗?看来我在 Instruments 中看到了这种行为。

  2. 如果是 2,如果没有“非自动释放”替代方案并且我正在使用我需要的 API,我是否应该忽略?另外,如果这段代码被多次调用,我应该完全重新考虑算法吗?

这是我的应用程序中的一些实用程序代码,它们经常被调用。基本上确定两个日期是否有意义地“相等”。我留下了注释掉的代码,所以你可以看到我在我的代码库中追求的改进类型——当我开始手动创建 NSDate(和发布)时,这个 DID 减少了随后在 Instruments 中运行时的内存泄漏帮助。但是,我仍然有我认为正在泄漏的日期组件对象......但它是一个 API 调用(抱歉代码格式,但我似乎无法改进它):

+ (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 调用(自动释放)返回的对象。不知道我还能做些什么来提高效率,我质疑我对如何最好地使用 Instruments 的理解。建议?

4

2 回答 2

4

自动释放的对象不应显示为内存泄漏。然而,有时 API 内部存在内存泄漏。您应该向苹果提交错误报告。NSCalendar 和 NSDateComponenets 等新类尤其值得怀疑。

至于保留与自动释放,一般规则是,除非您处于紧密循环中,否则这无关紧要。在这种情况下,如果紧密循环在没有事件离开的情况下进行了数千次,则意味着您永远不会“清理”自动释放池。

于 2009-03-24T22:06:07.323 回答
3

当使用像 GCD 这样的东西时,会有一个自动释放池,但你无法知道默认的自动释放池何时(如果有的话)被耗尽。如果您确信 atoreleased 对象没有释放,请确保您了解您正在使用的线程 API。如果内存为我提供了正确的 GCD 调用 (dispatch_async) 为您整理自动释放池,但池的实际耗尽可能需要很长时间。另一方面,NSOperations 让您拥有自己的自动释放池。

我已经看到 Instruments 中的内存泄漏检测依赖于 10 秒的间隔,导致错误的内存泄漏警告,这是由于在自动释放池耗尽之前的长时间延迟。所以尝试将有问题的代码包装在:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... [your code] ...
[pool drain];

我建议不要尝试用手动发布替换所有自动发布。使用自动释放会在一个地方产生平衡的保留/释放调用计数。在我看来,创建一个对象然后立即自动释放它可以防止很多内存错误。快,容易。使用手动发布调用时,您将忘记发布内容。在进行手动发布时,尤其是错误情况非常棘手。

自己做一个池可以为您提供更多控制权,并且在分配密集型工作期间,创建和耗尽您自己的池有时可能是有益的。但与往常一样,尝试和测试,不要做任何假设。

于 2011-04-05T11:58:58.033 回答