Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is calling close() after fopen() not closing?

Tags:

c++

c

file

io

I ran across the following code in one of our in-house dlls and I am trying to understand the behavior it was showing:

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;
}

After repeated calling of GetFD with the appropriate CloseFD, the whole dll would no longer be able to do any file IO. I wrote a tester program and found that I could GetFD 509 times, but the 510th time would error.

Using Process Explorer, the number of Handles did not increase.

So it seems that the dll is reaching the limit for the number of open files; setting _setmaxstdio(2048) does increase the amount of times we can call GetFD. Obviously, the close() is working quite right.

After a bit of searching, I replaced the fopen() call with:

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

    return 0;
}

Now, repeatedly calling GetFD/CloseFD works.

What is going on here?

like image 349
Richard Morgan Avatar asked Nov 27 '22 02:11

Richard Morgan


1 Answers

If you open a file with fopen, you have to close it with fclose, symmetrically.

The C++ runtime must be given a chance to clean up/deallocate its inner file-related structures.

like image 190
Vlad Avatar answered Dec 04 '22 09:12

Vlad