Подтвердить что ты не робот

Что произойдет, если я не позвоню fclose() в программе C?

Во-первых, я знаю, что открытие файла с fopen() и не закрытие его ужасно безответственно и плохой формы. Это просто явное любопытство, поэтому, пожалуйста, юморируйте меня:)

Я знаю, что если программа C открывает кучу файлов и никогда не закрывает ни одного из них, в конечном итоге fopen() начнет сбой. Есть ли другие побочные эффекты, которые могут вызвать проблемы вне самого кода? Например, если у меня есть программа, которая открывает один файл, а затем выходит без его закрытия, может ли это вызвать проблему для человека, запускающего программу? Может ли такая программа течь что-нибудь (память, дескрипторы файлов)? Могут ли возникать проблемы с доступом к этому файлу после завершения программы? Что произойдет, если программа будет выполняться много раз подряд?

4b9b3361

Ответ 1

Пока ваша программа работает, если вы продолжаете открывать файлы, не закрывая их, наиболее вероятным результатом является то, что у вас закончится дескрипторы/дескрипторы файлов, доступные для вашего процесса, и попытка открыть больше файлов в конечном итоге не удастся. В Windows это также может запретить другим процессам открывать или удалять открытые файлы, поскольку по умолчанию файлы открываются в режиме эксклюзивного совместного доступа, что предотвращает открытие других процессов.

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

Однако, еще одна проблема, которая должна быть осторожна - это буферизованные данные. Большинство файловых потоков хранят данные в памяти перед записью на диск. Если вы используете потоки FILE* из библиотеки stdio, есть две возможности:

  • Ваша программа вышла нормально, либо вызвав функцию exit(3), либо вернувшись из main (которая неявно вызывает exit(3)).
  • Ваша программа вышла аномально; это может быть вызвано abort(3) или _Exit(3), умирающим от сигнала/исключения и т.д.

Если ваша программа завершилась нормально, среда выполнения C позаботится о том, чтобы очистить любые буферизованные потоки, которые были открыты. Итак, если у вас были буферизованные данные, записанные в FILE*, который не был очищен, он будет сброшен при нормальном выходе.

И наоборот, если ваша программа вышла из строя, любые буферизованные данные не будут очищены. ОС просто говорит: "О, дорогая, ты оставил дескриптор файла открытым, я лучше закрываю это для тебя", когда процесс завершается; он не подозревает, что некоторые случайные данные лежат где-то в памяти, что программа предназначена для записи на диск, но не сделала этого. Поэтому будьте осторожны.

Ответ 2

В стандарте C говорится, что вызов exit (или, что то же самое, возврат из main) вызывает закрытие всех открытых объектов FILE as-if через fclose. Так что это прекрасно, за исключением того, что вы теряете возможность обнаруживать ошибки записи.

РЕДАКТИРОВАТЬ: Нет такой гарантии для аномального завершения (abort, неудачный assert, получение сигнала, поведение по умолчанию которого является аномальным завершением программы - обратите внимание, что там нет не обязательно любые такие сигналы - и другие средства, определенные реализацией). Как говорили другие, современные операционные системы будут очищать все видимые извне ресурсы, такие как открытые дескрипторы файлов уровня ОС; однако FILE, вероятно, не будет очищаться в этом случае.

Конечно, были ОС, которые не очищали внешние видимые ресурсы при аномальном завершении; он имеет тенденцию идти вперед, не применяя жесткие границы привилегий между "ядром" и "пользовательским" кодом и/или между различными процессами пользовательского пространства, просто потому, что, если у вас нет этих границ, это может быть невозможно сделать так безопасно в любом случае. (Рассмотрим, например, что произойдет, если вы напишете мусор над открытой файловой таблицей в MS-DOS, как вы вполне можете это сделать.)

Ответ 3

Предполагая, что вы выходите из-под контроля, используя системный вызов exit() или возвращаемый из main(), тогда открытые потоки файлов закрываются после промывка. Стандарт C (и POSIX) предусматривает это.

Если вы выйдете из-под контроля (core dump, SIGKILL) и т.д., или если вы используете _exit() или _exit(), открытые потоки файлов не сбрасываются (но дескрипторы файлов заканчиваются закрытыми, предполагая POSIX-подобную систему с файловыми дескрипторами - Standard C не указывает файловые дескрипторы). Обратите внимание, что _exit() задается стандартом C99, но _exit() предоставляется POSIX (но они действуют одинаково в системах POSIX). Обратите внимание, что дескрипторы файлов отделены от файловых потоков. См. Обсуждение "Последствия завершения программы" на странице POSIX для _exit(), чтобы узнать, что происходит, когда программа завершается в Unix.

Ответ 4

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