【问题标题】:Why is calling close() after fopen() not closing?为什么在 fopen() 不关闭后调用 close()?
【发布时间】:2010-04-07 12:40:14
【问题描述】:

我在我们的一个内部 dll 中遇到了以下代码,我试图了解它所显示的行为:

long GetFD(long* fd, const char* fileName, const char* mode)
{
    string fileMode;

    if (strlen(mode) == 0 || tolower(mode[0]) == 'w' || tolower(mode[0]) == 'o')
        fileMode = string("w");
    else if (tolower(mode[0]) == 'a')
        fileMode = string("a");
    else if (tolower(mode[0]) == 'r')
        fileMode = string("r");
    else
        return -1;

    FILE* ofp;
    ofp = fopen(fileName, fileMode.c_str());
    if (! ofp)
        return -1;

    *fd = (long)_fileno(ofp);
    if (*fd < 0)
        return -1;

    return 0;
}

long CloseFD(long fd)
{
    close((int)fd);
    return 0;
}

在使用适当的 CloseFD 重复调用 GetFD 后,整个 dll 将不再能够进行任何文件 IO。我写了一个测试程序,发现我可以GetFD 509次,但是第510次会出错。

使用 Process Explorer,Handles 的数量没有增加。

看来 dll 已达到打开文件数的限制;设置_setmaxstdio(2048) 确实增加了我们调用GetFD 的次数。显然,close() 工作得很好。

经过一番搜索,我将fopen() 调用替换为:

long GetFD(long* fd, const char* fileName, const char* mode)
{
    *fd = (long)open(fileName, 2);
    if (*fd < 0)
      return -1; 

    return 0;
}

现在,重复调用 GetFD/CloseFD 有效。

这里发生了什么?

【问题讨论】:

    标签: c++ c file io


    【解决方案1】:

    如果你用fopen 打开一个文件,你必须用fclose 对称地关闭它。

    必须让 C++ 运行时有机会清理/释放其内部与文件相关的结构。

    【讨论】:

    • 具体来说,您会留下一堆 FILE* 结构,并且一些操作系统为此有一个固定大小的表,通常为 512,其中包括 stdin、stdout 和 stderr FILE*s。
    • ... 这解释了 509 的限制:它只是 512 - stdin - stdout - stderr。
    • stdio 运行时,不仅仅是 C++(即 C 和 C++ 通用)。
    【解决方案2】:

    对于通过fopen 打开的文件,您需要使用fclose,或者对于通过open 打开的文件,您需要使用close

    【讨论】:

      【解决方案3】:

      您使用的标准库有一个FILE 结构的静态数组。因为你没有调用fclose(),所以标准库不知道底层文件已经关闭,所以它不知道可以复用对应的FILE结构。在 FILE 数组中的条目用完后会出现错误。

      【讨论】:

        【解决方案4】:

        fopen 打开它自己的文件描述符,因此您需要在原始函数中执行 fclose(ofp) 以防止文件描述符用完。通常,要么使用较低级别的文件描述符函数open, close,要么使用缓冲的fopen, fclose 函数。

        【讨论】:

          【解决方案5】:

          你正在打开文件 fopen() 函数,所以你必须使用 fclose() 关闭文件,如果你正在使用 open() 函数并尝试调用 fclose() 函数它将不起作用

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-09-18
            • 1970-01-01
            • 1970-01-01
            • 2013-09-11
            • 2018-02-26
            • 1970-01-01
            • 2011-06-23
            • 2017-01-13
            相关资源
            最近更新 更多