iOS - 调用contentsOfDirectoryAtPath在循环中泄漏内存

时间:2013-11-22 00:53:46

标签: ios iphone objective-c

我不太熟悉objective-c,所以如果这是一个愚蠢的问题,请原谅我。我已经创建了一个后台线程来解析目录中存在的文件列表,目录中的文件可以随时更改。

我在循环的每次迭代中调用“contentsOfDirectoryAtPath”,我的分配突然超过300mb。我无法弄清楚如何让ARC释放返回的数组。有人可以指点我在这里正确的方向吗?

-(void) offlineModeThread
{

    NSString *dataDir = [ViewController getDataDirectory];
    NSFileManager *nfm = [NSFileManager defaultManager];

    while(1)
    {
        NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil];
        /*
        if(files == nil)
            break;

        if([files count] <= 0)
        {
            files = nil;
            [NSThread sleepForTimeInterval: 5.0f];
            continue;
        }

        if(![ViewController obtainLock])
        {
            files = nil;
            continue;
        }
        */
        //[ViewController releaseLock];
        files = nil;
    }

}

正如您所看到的,我尝试通过将'files'设置为nil来释放数组,但它不起作用。

2 个答案:

答案 0 :(得分:1)

你是如何创建这个帖子的? NSThread? NSOperation和NSOperationQueue? GCD?

对于NSThread和NSOperation,您应该在设置线程时创建自己的自动释放池。这样就可以在该线程中正确管理临时对象。

我相信GCD会为您处理这个细节。

在较新版本的Objective C(Objective C 2.0,我相信)中,您应该使用新语法

@autoreleasepool
{
   //Code to use a local autorelease pool
}

对于生成大量临时对象的循环,您可以为任何代码块创建本地自动释放池。您可以像这样重构代码:

while(1)
{
  @autoreleasepool
  {
    NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil];
    /*
    if(files == nil)
        break;

    if([files count] <= 0)
    {
        files = nil;
        [NSThread sleepForTimeInterval: 5.0f];
        continue;
    }

    if(![ViewController obtainLock])
    {
        files = nil;
        continue;
    }
    */
    //[ViewController releaseLock];
    files = nil;
  }
}

这将导致它为循环的每次迭代创建一个新的自动释放池,并在最后排出它(从而释放在该迭代中创建的所有临时对象。)

顺便说一句,如果您使用的是NSThread,请不要。了解如何使用GCD。 GCD(Grand Central Dispatch)比NSThread更有效地使用系统资源。 NSThread基于POSIX线程,创建起来非常昂贵,并且可以在设备的生命周期内占用物理内存。

NSOperationQueues已经在最近的操作系统版本中进行了重构,以便在幕后使用GCD,因此它们在内部同样有效,尽管在大多数情况下使用GCD比使用GCD更难。

答案 1 :(得分:0)

嗯,我认为答案很明显。请查看documentation

  

许多程序会创建自动释放的临时对象。这些   对象添加到程序的内存占用,直到结束   块。在许多情况下,允许临时对象累积   直到当前事件循环迭代结束才导致   过度开销;但是,在某些情况下,您可以创建一个   大量临时对象大量增加内存   足迹和你想要更快地处置。在这些   在后一种情况下,您可以创建自己的自动释放池块。在   块的结尾,临时对象被释放,这通常是   导致他们的释放,从而减少程序的内存   足迹。

你可以看到这个question

因此,解决方案是使用您的@autoreleasepool{},因为您正在创建许多临时对象。