代码之家  ›  专栏  ›  技术社区  ›  Dov

调试Mac/Cococa文件描述符泄漏

  •  2
  • Dov  · 技术社区  · 10 年前

    我的沙盒Mac应用程序(显然)正在泄漏文件资源(句柄?)。在向其中添加文件(并将其中一些文件转换为其他格式)时 -[NSFileManager copyItemAtPath:toPath:error:] 具有以下基本错误:

    NSUnderlyingError=0x600000440a50 "The operation couldn’t be completed. Too many open files"
    

    我可以在Xcode外部(使用Debug构建)可靠地再现这种情况,但永远不会在内部。看起来某个文件正在打开,但从未关闭。每次当我删除同一个文件夹时,都会在同一个文件上发生这种情况,如果我取出该文件,则会在下一个文件夹中发生这种情况。我记录了我能想到的每个地方,我在那里进行文件I/O NSFileManager ,看起来我所有的打开调用都与关闭调用相平衡,启动和停止安全资源访问的调用也是如此 NSURLs .

    1. 为什么这不会发生在Xcode内部?
    2. 我如何追踪不平衡呼叫的发生位置?
    3. 这个错误有可能是在转移注意力吗?

    我试着用 文件活动 预设,并能够再现其中的错误,但似乎没有任何方法可以从所使用的工具(文件活动、读取/写入、文件属性、目录I/O)中获取所需的信息。

    1 回复  |  直到 10 年前
        1
  •  1
  •   Dov    10 年前

    我最终能够使用仪器找出根本原因。我整理了 文件属性 仪器的事件列表,并且能够看到同一文件描述符有许多“打开”事件(以及同一文件和不同描述符的一些事件),没有任何“关闭”事件。我能够找到我使用的库中的违规代码。我在 unit tests ,使用此方法并在运行某些代码之前和之后进行比较:

    - (NSInteger)numberOfOpenFileHandles {
        int pid = [[NSProcessInfo processInfo] processIdentifier];
        NSPipe *pipe = [NSPipe pipe];
        NSFileHandle *file = pipe.fileHandleForReading;
    
        NSTask *task = [[NSTask alloc] init];
        task.launchPath = @"/usr/sbin/lsof";
        task.arguments = @[@"-P", @"-n", @"-p", [NSString stringWithFormat:@"%d", pid]];
        task.standardOutput = pipe;
    
        [task launch];
    
        NSData *data = [file readDataToEndOfFile];
        [file closeFile];
    
        NSString *lsofOutput = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
    
    //    NSLog(@"LSOF:\n%@", lsofOutput);
    
        return [lsofOutput componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]].count;
    }