Fclose немедленно освобождает файл? - PullRequest
0 голосов
/ 09 мая 2018

У меня есть 2 функции. Первая функция - открыть файл в режиме записи, записать в него некоторое содержимое, а затем закрыть его.

FILE *fp = fopen("file.txt", "w");
//writing itnot file using fwrite
fclose(fp);

Вторая функция открывает файл в режиме чтения, анализирует содержимое и затем закрывает файл.

FILE *fp = fopen("file.txt", "r");
//parsing logic
fclose(fp);

В main я звоню function1 и function2 последовательно.

int main()
{
    function1();
    function2();
    return 1;
}

Иногда function1 fopen завершается неудачно с ошибкой номер 13, то есть отказано в разрешении. Я наблюдаю это только иногда. Я ввел sleep в function1 после fclose в течение 2 секунд, и он начал работать без проблем.

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

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

В среде и с реализацией C, где вы должны приспосабливаться к такому поведению, наилучшим подходом, вероятно, является реализация некоторой отказоустойчивости вокруг fopen() s. Хотя безусловный sleep() не является правильным ответом, короткие, условные задержки с помощью sleep() или аналогичной функции действительно могут быть частью такой стратегии. Например, вы можете сделать что-то вроде этого:

#include <stdio.h>
#include <errno.h>
#define MAX_ATTEMPTS 3

FILE *tolerant_fopen(const char *path, const char *mode) {
    FILE *result;
    int attempts = 0;

    while (!(result = fopen(path, mode))) {
        if (errno != EACCES || attempts >= MAX_ATTEMPTS) {
            break;
        }
        if (sleep(1) == 0) {
            attempts += 1;
        }
    }

    return result;
}

При попытке открыть файл немедленно, а в случае сбоя из-за разрешений на доступ он некоторое время ждет, а затем делает еще одну попытку. В целом, он может сделать три или более попыток открыть файл с интервалом в одну секунду или, возможно, чуть больше. (Обратите внимание, что sleep() может быть прервано досрочно; в этом случае он возвращает количество секунд, оставшихся до сна.)

Конечно, вы можете реализовать другую стратегию для определения времени и продолжительности повторных попыток, если хотите, повторить больше ошибок, и т. Д. ..

0 голосов
/ 09 мая 2018

В проекте N1570 для C11 указано 7.21.5.1 Функция fclose

При успешном вызове функции fclose поток, на который указывает поток, будет очищен и связанный файл должен быть закрыт. Любые неписанные буферизованные данные для потока доставляются в хост-среду для записи в файл; любые непрочитанные буферизованные данные отбрасываются. Независимо от того, успешен ли вызов, поток отсоединяется от файла и любой буфер, установленный функцией setbuf или setvbuf, отсоединяется от потока (и освобождается, если он был автоматически выделен).

Он не делает никаких предположений о том, что происходит на уровне среды хоста, то есть функция возвращает только после завершения всей операции или возвращает, как только запрос был поставлен в очередь.

Поскольку в вашей среде могут возникнуть условия гонки, вам следует несколько раз повторить попытку неудачного открытия, в конечном итоге с задержкой между ними. Если переносимость не является проблемой и если ваша система поддерживает функцию POSIX sync, вы также можете принудительно выполнить синхронизацию файла на диске после его закрытия:

  • Закрыть:

    ...
    fclose(fp)
    sync();         // forces synchronization of io buffers to disk 
    
  • Повторное открытие детали

    ntries = ...;   // number of open tries
    while (ntries-- > 0) {
        fp = fopen(...);
        if (fp != NULL) break;   // open was successful
        // optionaly add a delay
    }
    
...