#c #file #io
#c #файл #io
Вопрос:
#include <stdio.h>
int main(void) {
FILE *fp = fopen("hello.txt", "r");
if (fp == NULL) {
fputs("hello.txt failed to openn", stderr);
return 0;
}
/* do some stuff with the file */
if (fclose(fp) == EOF) {
/* what should I do? we can't just leave a file open */
}
return 0;
}
fclose
может произойти сбой, но если не удается закрыть файл, что мне делать? Мы не можем просто оставить файл открытым. Будем ли мы продолжать закрывать файл, пока он не завершится сбоем? Что бы вы, ребята, сделали?
Комментарии:
1. Если файл был открыт для чтения, никаких действий по исправлению ситуации предпринимать не стоит. Обратите внимание, что любой открытый файл будет закрыт системой при выходе из программы.
2. Если вы находитесь в размещенной среде, не напрягайтесь. Ваша программа не несет ответственности за устранение всех проблем в системе, в которой она работает. Вы можете напечатать описательную ошибку в stderr, а затем завершить процесс с кодом, сигнализирующим об ошибке.
3. Используйте
fflush()
для точек, где вам нужно выполнить запись в файл.4. По крайней мере, в Linux на странице руководства для базового
close(2)
вызова указано не повторять попытку после ошибки, fwiw.5. И что более важно, похоже, что стандарт гласит, что использование указателя ФАЙЛА для чего-либо после
fclose()
, независимо от того, возвращает он ошибку или нет, не определено.
Ответ №1:
Любое использование FILE
указателя после его вызова fclose()
(независимо от fclose()
того, указывает ли он на ошибку или нет) является неопределенным поведением *.
Итак, лучшее, что вы можете сделать, это зарегистрировать ошибку и продолжить работу вашей программы. В зависимости от того, что он делает, также возможен выход со статусом ошибки.
* В разделе 7.21.3 проекта C11 говорится:
Значение указателя на файловый объект не определено после закрытия связанного файла
И в документации POSIX говорится:
После вызова
fclose()
любое использованиеstream
приводит к неопределенному поведению.
Ответ №2:
Ошибка при включении fclose
не означает, что система отказалась закрыть файл. Это редко должно происходить с файлами, открытыми для чтения, и тогда это может быть только следствием аппаратного сбоя или серьезной ошибки в файловой системе или ядре, а не с вещами, с которыми должна иметь дело обычная программа: просто зарегистрируйте или сообщите об ошибке, если можете. И в любом случае, после вызова fclose
дескриптора больше никогда не следует использовать, независимо от того, произошла ошибка или нет.
Но когда файлы были открыты для записи и используется буферизация, fclose
может возникнуть ошибка, если не удалось завершить последние операции записи, которые все еще находятся в очереди. Здесь причиной может быть ошибка превышения квоты, переполнение файловой системы или любая другая ошибка, о которой может сообщить fwrite
. Таким образом, в этом случае ошибка on fclose
может быть обработана так же, как вы обработали ошибки в предыдущем fwrite
. Ни больше, ни меньше, за исключением того, что вы больше не можете использовать дескриптор файла.
Ответ №3:
Описание fclose
в стандарте гласит:
- Успешный вызов
fclose
функции приводит к сбросу потока, на который указываетstream
, и закрытию связанного файла. Любые неписаные буферизованные данные для потока доставляются в среду хоста для записи в файл; любые непрочитанные буферизованные данные отбрасываются. Независимо от того, выполняется ли вызов успешно или нет, поток отсоединяется от файла, и любой буфер, установленный функциейsetbuf
orsetvbuf
, отсоединяется от потока (и освобождается, если он был выделен автоматически).
Таким образом, если fclose
сбой, то не совсем гарантировано, что дескриптор файла был переработан или файл был закрыт должным образом, но FILE
на который указывает by stream
, больше нельзя использовать, потому что файл был отделен от него, а буферы освобождены.
Обратите внимание, что это fclose
может привести к сбою, например, если некоторые данные хранились в буферах, а на диске не хватает места. Если вы заботитесь о корректной записи данных, используйте fflush
для очистки данных и обработки ошибок, например, попросите пользователя освободить больше места на диске или что-то подобное; в отличие от этого fclose
, вы всегда можете повторить попытку fflush
позже.