我的沙盒 Mac 应用程序(显然)正在泄漏文件资源(句柄?)。在向其中添加文件(并将其中一些文件转换为不同的格式)时,它将在 -[NSFileManager copyItemAtPath:toPath:error:]
上失败,并出现以下潜在错误:
NSUnderlyingError=0x600000440a50 "The operation couldn’t be completed. Too many open files"
我可以在 Xcode 外部(使用调试版本)可靠地重现此内容,但不能在内部重现。看起来某个地方的文件正在被打开并且从未关闭。当我删除同一个文件夹时,每次在同一个文件上都会发生这种情况,或者如果我取出该文件,则在下一个文件夹上会发生这种情况。我记录了我能想到的在 NSFileManager
之外进行文件 I/O 的每个位置,看起来我所有的打开调用都与关闭保持平衡,启动和停止的调用也是如此NSURL
上的安全资源访问。
- 为什么这不会在 Xcode 中发生?
- 如何追踪不平衡调用发生的位置?
- 这个错误有可能是转移注意力吗?
我尝试使用文件事件预设在 Xcode 之外的 Instruments 中运行,并且能够重现其中的错误,但看起来没有任何方法可以获取我的信息所使用工具的需求(文件事件、读/写、文件属性、目录 I/O)。
最佳答案
我最终能够使用 Instruments 找出根本原因。我按 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;
}
关于xcode - 调试 Mac/Cocoa 文件描述符泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25005213/