【问题标题】:fgets is reading more data from a closed filedescriptorfgets 正在从关闭的文件描述符中读取更多数据
【发布时间】:2011-09-07 17:29:18
【问题描述】:

我在 linux 上遇到了 fgets() 的一些问题。 fgets 正在从关闭的文件描述符中返回数据。 如果文件关闭,我希望它返回 EOF。 我能够想出我的问题的简化版本。

int main()
{
        int i=0, j;
        FILE *FD;
        char p[128];
        FD = fopen("junk", "r");
        while(fgets(p, sizeof(p), FD))
        {  
                close(fileno(FD));
                printf("lineno=%d\n", i++);
        }  
        return 0;
}

我希望它只打印一行。 这个问题有解决办法吗?

更新: 正如下面有人回答的那样, fgets 正在缓冲文件 并在 FD 关闭后返回给我数据。 它正在缓冲 4kB 的数据。如果文件大小超过 4k, 它在读取 4KB 后得到 EOF 并且打印停止。否则,如果 文件大小小于 4k,它会打印到文件末尾。

【问题讨论】:

    标签: c linux file-io eof fgets


    【解决方案1】:

    在关闭的文件上调用 fgets() 具有未定义的行为。也就是说,不保证返回EOF。

    【讨论】:

      【解决方案2】:

      正如其他人所说,close(fileno(FD)); 是个坏主意。如果你这样做,相同的文件描述符可能会被另一个文件重用,fgets 会突然读取那个 fd。这尤其适用于多线程应用程序。

      此外,fgets 是缓冲的。它可能在第一次调用时从文件中读取了大量数据,随后的调用只是从缓冲区返回更多数据。

      相反,请执行以下操作:

      int main(void)
      {
              int i=0, j;
              FILE *FD;
              char p[128];
              FD = fopen("junk", "r");
              while(FD && fgets(p, sizeof(p), FD))
              {  
                      fclose(FD);
                      FD = NULL;
                      printf("lineno=%d\n", i++);
              }  
              return 0;
      }
      

      【讨论】:

      • 是的,fgets 的缓冲似乎是个问题。它似乎正在缓冲高达 4kB 的数据。我在 4kB 后得到 EOF。
      【解决方案3】:

      在关闭文件描述符后使用它可能会导致不可预测/未定义的行为。您可能应该避免这样做。

      在发布的示例中可能发生的是流被打开和读取。读取数据可能会将更多数据放入底层流中。因此,即使底层文件描述符已关闭,流的句柄仍将包含更多要读取的数据。同样,这可能是不可预测的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-04
        • 2017-09-05
        • 1970-01-01
        相关资源
        最近更新 更多