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

时间:2014-07-28 22:13:35

标签: xcode macos cocoa instruments file-descriptor

我的沙盒Mac应用程序(显然)正在泄漏文件资源(句柄?)。在向其添加文件(并将其中一些文件转换为其他格式)时,-[NSFileManager copyItemAtPath:toPath:error:]上的文件会因此隐藏错误而失败:

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

我可以在Xcode之外(使用Debug版本)可靠地重现这个,但从不在里面。看起来某个地方的文件正在被打开而且从未关闭过。当我删除相同的文件夹时,它每次都出现在同一个文件中,如果我取出该文件,则会发生下一个文件。我记录了每个我能想到的地方我在NSFileManager之外进行文件I / O的操作,看起来我的所有打开调用都与关闭平衡,我的调用启动和停止安全NSURLs上的资源访问。

  1. 为什么在Xcode内部会发生这种情况?
  2. 如何追踪不平衡电话的发生位置?
  3. 错误是否可能是红鲱鱼?
  4. 我尝试使用文件活动预设在Xcode之外的仪器中运行,并且能够重现其中的错误,但它看起来没有任何方法可以获得我需要的信息来自所使用的工具(文件活动,读/写,文件属性,目录I / O)。

1 个答案:

答案 0 :(得分:1)

我最终能够使用仪器找出根本原因。我通过FD列对文件属性工具的事件列表进行了排序,并且能够看到有很多"打开"相同文件描述符的事件(以及相同文件和不同描述符的一些事件),没有任何"关闭"事件。我能够将违规代码追踪到我使用的库中。我在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;
}