为什么在fopen()没有关闭后调用close()?

时间:2010-04-07 12:40:15

标签: c++ c file io

我在我们的一个内部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可以正常工作。

这里发生了什么?

5 个答案:

答案 0 :(得分:17)

如果您使用fopen打开文件,则必须以fclose对称关闭它。

必须为C ++运行时提供清理/解除分配其内部文件相关结构的机会。

答案 1 :(得分:8)

您需要将fclose与通过fopen打开的文件一起使用,或close打开通过open打开的文件。

答案 2 :(得分:5)

您使用的标准库具有FILE结构的静态数组。因为您没有调用fclose(),所以标准库不知道底层文件已被关闭,因此它不知道它可以重用相应的FILE结构。在FILE数组中的条目用完后,您会收到错误。

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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