延迟打开的文件导致“打开的文件太多”

Posted

技术标签:

【中文标题】延迟打开的文件导致“打开的文件太多”【英文标题】:Lingering open files resulting in "Too many open files" 【发布时间】:2012-01-24 08:21:29 【问题描述】:

我的代码使用 boost 来列出目录内容、遍历每个文件并进行一些数据处理。结果被打印到输出文件('histFile')。 处理了 ~2555 个文件后,出现错误:

boost::filesystem::directory_iterator::construct:打开的文件太多:“/Users/.../.../.../directory_with_files”

我的代码是:

for(int i = 0; i < 10000; i++) 
    FILE *histFile;
    string outputFileName = "somename";
    bool ifRet = initFile(histFile, outputFileName.c_str(), "a");   // 1
    fclose(histFile);                                               // 2

如果我注释掉上面的最后两行('1' 和 '2'),代码就完成了。因此,“histFile”的副本似乎处于打开状态,但我不明白如何!这是该方法的操作部分:

bool initFile(FILE *&ofFile, const char *fileName, const char *openType, int overwriteOption) 

if(overwriteOption < 0 || overwriteOption > 2) 
    fprintf(stderr, "ERROR: ToolBox - initFile() : unknown 'overwriteOption' (%d), setting to (0)!\n", overwriteOption);


// Read-Only
if(openType == "r") 
    if(ofFile = fopen(fileName, "r"))  return true; 
    fprintf(stderr, "ERROR: Could not open file (%s)!\n", fileName);
    return false;


// Appending:
if(openType == "a" || openType == "a+") 
    // Check if file already exists
    if(!fopen(fileName, "r"))
        fprintf(stderr, "ERROR: (%s) File does not Exist, cannot append!\n", fileName);
        return false;
       
    if(ofFile = fopen(fileName, openType))  return true;      


// Writing:
//    if file already exists
if(FILE *temp = fopen(fileName, "r"))
    if(overwriteOption == 2) 
        fprintf(stderr, "ERROR: (%s) File Exists!\n", fileName);
        return false;
    
    if(overwriteOption == 1) 

    
    if(overwriteOption == 0) 
        char backupFileName[TB_CHARLIMIT], backupPrefix[TB_CHARLIMIT];
        strcpy(backupFileName, fileName);                                  // copy filename
        // create a prefix w/ format '<YYYYMMDD>BACKUP_'
        DateTime now;
        sprintf(backupPrefix, "%s", now.getDateStr().c_str());
        strcat(backupPrefix, "BACKUP_");
        // add to copied filename, and move file
        strcpy(backupFileName, prependFileName(backupFileName, backupPrefix));
        moveFile(fileName, backupFileName);
       
    fclose(temp);
 

if(ofFile = fopen(fileName, openType))  return true; 


// Default: Return error and false 
fprintf(stderr, "ERROR: Could not open file (%s)!\n", fileName);
return false;
 

我对指针/引用做错了吗? 非常感谢任何帮助!

【问题讨论】:

您是说您发布的代码显示了问题吗?我没有看到任何提升,那么 boost::filesystem 与这个问题有什么关系? 您可能需要显示 initFile 的其余部分 - 我怀疑它会引发异常,然后泄漏打开的文件。 @Paur R:如果它抛出异常,那么循环的其余部分将不会被执行。所以这不可能。 @TonyK 这也意味着不再打开文件。如果未捕获到异常,程序将终止并关闭所有文件,因此在任何一种情况下都不会泄漏文件句柄。 好的 - 我认为看到 initFile 的其余部分仍然很有用 【参考方案1】:

当您测试文件是否已经存在时,您在这段代码中泄漏了句柄:

// Appending:
if(openType == "a" || openType == "a+") 
    // Check if file already exists

    if(!fopen(fileName, "r"))     //  <-- the FILE* opened here is leaked

        fprintf(stderr, "ERROR: (%s) File does not Exist, cannot append!\n", fileName);
        return false;
       
    if(ofFile = fopen(fileName, openType))  return true;      

真的有理由进行检查吗?如果文件不存在,为什么不直接创建它?

【讨论】:

谢谢!就是这样。没有“真正的”理由;只是清洁。

以上是关于延迟打开的文件导致“打开的文件太多”的主要内容,如果未能解决你的问题,请参考以下文章

打开 WebSocket 会导致 Google App Engine 上出现延迟峰值

Google pubsub_v1 订阅者拉“打开的文件太多”

消息延迟是异步吗

Haskell - 延迟评估是不是会导致此文件夹停止评估所有功能

键盘延迟修改

从 TableView 打开 ViewController 时有几秒钟的延迟