Почему вызов close () после fopen () не закрывается? - PullRequest
4 голосов
/ 07 апреля 2010

Я наткнулся на следующий код в одной из наших собственных библиотек и пытаюсь понять поведение, которое он демонстрирует:

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

После повторного вызова GetFD с соответствующим CloseFD весь dll больше не сможет выполнять какой-либо файловый ввод-вывод. Я написал программу-тестер и обнаружил, что могу получить GetFD 509 раз, но 510-й раз приведет к ошибке.

При использовании Process Explorer количество дескрипторов не увеличивалось.

Таким образом, похоже, что 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 ]

17 голосов
/ 07 апреля 2010

Если вы открываете файл с помощью fopen, вы должны закрыть его с помощью fclose, симметрично.

Среде выполнения C ++ должна быть предоставлена ​​возможность очистить / освободить свои внутренние структуры, связанные с файлами.

8 голосов
/ 07 апреля 2010

Вам необходимо использовать fclose с файлами, открытыми через fopen, или close с файлами, открытыми через open.

5 голосов
/ 07 апреля 2010

Стандартная библиотека, которую вы используете, имеет статический массив структур FILE. Поскольку вы не вызываете fclose(), стандартная библиотека не знает, что основные файлы были закрыты, поэтому она не знает, что может повторно использовать соответствующие структуры FILE. Вы получаете сообщение об ошибке после исчерпания записей в массиве FILE.

3 голосов
/ 07 апреля 2010

fopen открывает свой собственный файловый дескриптор, поэтому вам нужно будет сделать fclose(ofp) в исходной функции, чтобы предотвратить исчерпание файловых дескрипторов. Обычно один из них использует функции дескриптора файла более низкого уровня open, close ИЛИ буферизованные функции fopen, fclose.

2 голосов
/ 07 апреля 2010

вы открыли функцию file fopen (), поэтому вам нужно закрыть файл, используя fclose (), если вы используете функцию open () и попытаетесь вызвать функцию fclose (), она не будет работать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...