В чем смысл fclose()?

Из того, что я прочитал, fclose() в основном похож на free() при выделении памяти, но я также читал, что операционная система закроет этот файл для вас и очистит все открытые потоки сразу после его завершения. Я даже протестировал несколько программ без fclose(), и все они работают нормально.


person Cast    schedule 08.11.2015    source источник
comment
Что делать, если ваша программа работает много часов и хочет открывать и закрывать множество файлов? Вам также не нужно free() память, но если вы этого не сделаете, в какой-то момент вы израсходуете все ресурсы.   -  person 5gon12eder    schedule 09.11.2015
comment
Если вы все равно собираетесь выйти, тогда среда выполнения C позаботится об этом за вас, и нет смысла делать это вручную. Возможно, вы могли бы использовать его для очистки вывода в случае, если вы подозреваете, что очистка может дать сбой. В более длительном случае вы можете использовать его для освобождения ресурсов, существует конечное количество слотов для файлов, и сохранение файла открытым часто блокирует его, так что к нему нельзя получить свободный доступ из других приложений, пока ваше собственное не выйдет.   -  person doynax    schedule 09.11.2015
comment
Я видел более одного случая, когда файловый дескриптор был закрыт нормально, но ожидающие буферы записи НЕ сбрасывались, в результате чего файлы имели длину 0,   -  person Martin James    schedule 09.11.2015


Ответы (2)


Длительному процессу (например, базе данных или веб-браузеру) может потребоваться открыть много файлов за время своего существования; хранение неиспользуемых файлов открытыми приводит к трате ресурсов и потенциально блокирует использование файлов другими процессами.

Кроме того, fclose очищает буфер пользовательского пространства, который часто используется при записи в файлы для повышения производительности; если процесс завершается без очистки этого буфера (с fflush/fclose), данные, все еще находящиеся в буфере, будут потеряны.

person Colonel Thirty Two    schedule 08.11.2015

Большинство современных операционных систем также восстанавливают память, которую вы malloc() выделили, но использование free(), когда это уместно, по-прежнему является хорошей практикой. Дело в том, что, как только вам больше не нужен ресурс, вы должны отказаться от него, чтобы система могла переназначить любые резервные ресурсы, которые были освобождены, для использования другими приложениями (обычно это память). Также существуют ограничения на количество файловых дескрипторов, которые вы можете держать открытыми одновременно.

Кроме того, есть дополнительные соображения в случае open() и его друзей, в частности, по умолчанию дескрипторы открытых файлов наследуются через поток и fork() границы процесса. Это означает, что если вы не close() файловых дескрипторов, вы можете обнаружить, что дочерний процесс может получить доступ к файлам, открытым родительским процессом. Обычно это нежелательно, это тривиальная дыра в безопасности, если вы хотите, чтобы привилегированный родительский процесс порождал подчиненный процесс с меньшими привилегиями.

Кроме того, семантика unlink() и друзей заключается в том, что содержимое файла «удаляется» только после того, как последний открытый файловый дескриптор файла становится close(), поэтому еще раз: если вы держите файлы открытыми дольше, чем это строго необходимо, вы вызываете неоптимальное поведение в общая система.

Наконец, в случае сокетов close() также соответствует отключению от удаленного партнера.

person user268396    schedule 08.11.2015
comment
Насколько я знаю, ни одна ОС не восстанавливает память, выделенную malloc. Насколько я понимаю, ОС обычно даже не знает о malloc/free, поскольку они происходят исключительно внутри пользовательского пространства процесса. Даже с соответствующими вызовами ядра для выделения/освобождения страниц ядро ​​ОС будет восстанавливать только те страницы процесса, о которых этот процесс конкретно сообщает ему. Он не будет пытаться восстановить страницы памяти самостоятельно. - person Dreamer; 09.11.2015
comment
@Dreamer: ОС полностью осведомлена о том, какие страницы памяти в настоящее время заняты теми или иными процессами. Если процесс умирает, AFAIK эти страницы не отображаются (если ни один другой процесс не использует те же самые страницы), эффективно освобождая физическую память для будущего использования. Конечно, в реальном времени/встроенном пространстве существует множество ОС, которые на самом деле не выполняют пейджинг или виртуальную память. - person user268396; 09.11.2015
comment
@ user268396 правильно. Любая нетривиальная ОС обязательно освободит любые страницы, которые больше не требуются ни одному процессу. Ядро не знает и не заботится о подраспределителях, таких как malloc, только о своих собственных данных состояния диспетчера виртуальной памяти. Когда процесс завершается, ОС может и будет останавливать все его потоки, а затем освобождать все страницы памяти и другие ресурсы, которые не используются совместно. Если бы этого не произошло, «убить-9» и «Завершить процесс» диспетчера задач были бы в лучшем случае неэффективными. - person Martin James; 09.11.2015
comment
@user268396 user268396: да, ОС восстанавливает страницы завершенных процессов. А я и не утверждал обратного. Но ОС знает только, какой процесс владеет какими страницами. Он не знает, какая часть каких страниц занята malloc — если вообще есть. И поэтому ОС не может вернуть страницы из процесса, пока либо процесс не завершится, либо сам процесс не даст указание ОС вернуть указанные страницы. Вот почему я считаю ваше первоначальное утверждение о том, что ОС восстанавливает память, которую вы выделили, неверным. - person Dreamer; 10.11.2015