Если по какой-то причине я обнаружил фатальную ситуацию в моей программе, и мне бы хотелось выйти с кодом ошибки. Иногда контекст фатальной ошибки выходит за рамки других дескрипторов файлов. это хорошая практика для закрытия этих файловых дескрипторов. Насколько я знаю, эти файлы автоматически закрываются, когда процесс умирает.
Это хорошая практика закрыть дескрипторы файлов при выходе
Ответ 1
Файлы автоматически закрываются, но это хорошая практика.
См. valgrind в этом примере
[email protected]:~$ cat demo.c
#include <stdio.h>
int main(void)
{
FILE *f;
f = fopen("demo.c", "r");
return 0;
}
[email protected]:~$ valgrind ./demo
==3959== Memcheck, a memory error detector
==3959== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3959== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3959== Command: ./demo
==3959==
==3959==
==3959== HEAP SUMMARY:
==3959== in use at exit: 568 bytes in 1 blocks
==3959== total heap usage: 1 allocs, 0 frees, 568 bytes allocated
==3959==
==3959== LEAK SUMMARY:
==3959== definitely lost: 0 bytes in 0 blocks
==3959== indirectly lost: 0 bytes in 0 blocks
==3959== possibly lost: 0 bytes in 0 blocks
==3959== still reachable: 568 bytes in 1 blocks
==3959== suppressed: 0 bytes in 0 blocks
==3959== Rerun with --leak-check=full to see details of leaked memory
==3959==
==3959== For counts of detected and suppressed errors, rerun with: -v
==3959== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
Как вы можете видеть, он вызывает утечку памяти
В некоторых случаях вы можете использовать atexit()
:
#include <stdio.h>
#include <stdlib.h>
static FILE *f;
static void free_all(void)
{
fclose(f);
}
static int check(void)
{
return 0;
}
int main(void)
{
atexit(free_all);
f = fopen("demo.c", "r");
if (!check()) exit(EXIT_FAILURE);
/* more code */
return 0;
}
Ответ 2
В классическом руководстве по программированию POSIX "Расширенное программирование в среде UNIX" указано:
Когда процесс завершается, все его открытые файлы автоматически закрываются ядром. Многие программы используют этот факт и явно не закрывают открытые файлы.
Вы не упомянули ОС в своем вопросе, но такое поведение следует ожидать от любой ОС. Всякий раз, когда поток управления программой пересекает exit()
или return
от main()
, система должна очищать после процесса.
В ОС всегда существует опасность ошибок. Но, с другой стороны, система должна освободить более чем несколько дескрипторов открытых файлов при завершении процесса: память, занятая исполняемым файлом, стек, объектами ядра, связанными с процессом. Вы не можете управлять этим поведением из пользовательского пространства, вы просто полагаетесь на его работу по назначению. Итак, почему программист не может полагаться на автоматическое закрытие fd
s?
Таким образом, единственная проблема с открытием fd
open может быть вопросом стиля программирования. И, как и в случае использования объектов stdio
(т.е. Материала, созданного с помощью файла ввода-вывода, предоставленного системой), вы можете получать (несколько) дезориентирующие предупреждения во время valgrinding. Что касается опасности утечки системных ресурсов, то не о чем беспокоиться, если ваша реализация ОС действительно не работает.
Ответ 3
Насколько я знаю, эти файлы автоматически закрываются, когда процесс умирает.
Не полагайтесь на это. Концептуально, когда процесс умирает, ваша ответственность освобождает выделенную память, закрывает нестандартные дескрипторы файлов и т.д. Конечно, каждая нормальная ОС (и даже Windows) будет очищаться после вашего процесса, но этого не стоит ожидать.
Ответ 4
Да. Предположим, что ваша основная программа теперь является классом в отдельной программе. Теперь вы просто описали утечку ресурсов. Вы, по сути, нарушаете инкапсуляцию, полагаясь на глобальное состояние программы, то есть на состояние процесса, а не на ваш модуль, а не на класс, а не на ADT, а не на поток, но весь процесс находится в состоянии выключения.
Ответ 5
На языке C нет гарантии, что ОС будет делать что-то о том, что вы оставили позади. Он выходит за рамки стандарта программирования. Хотя C подразумевает, что вы вызываете все стандартные функции очистки (malloc fclose и т.д.), Как вы должны делать.
Таким образом, все зависит от ОС. Поскольку ваш вопрос не касается конкретной ОС, на него нельзя ответить. В настоящее время все основные коммерческие настольные ОС делают очистку, но это не повод для практики неаккуратного программирования.
И тогда предположим, что ваша программа не соответствует процессу/исполняемому файлу ОС, но она состоит из потока, Windows DLL, драйвера или аналогичного, существующего в том же пространстве памяти, что и родительский процесс. Затем вы утешаете ресурсы и крадете память у родителя.
Ответ 6
C гарантирует, что все открытые файлы будут закрыты, если ваша программа завершится нормально (т.е. через exit
или возврат из main
). Однако, если ваша программа прерывается ненормально, например, он закрывается операционной системой из-за использования указателя NULL, вплоть до операционной системы для закрытия файлов. Поэтому рекомендуется закрыть файлы, если они больше не нужны в случае неожиданного завершения.
Другая причина - ограничения ресурсов. Большинство операционных систем имеют ограничения на количество открытых файлов (как и многие другие), и поэтому хорошей практикой является возвращение этих ресурсов, как только они больше не нужны. Если каждая программа хранит все свои файлы неограниченно, системы могут столкнуться с проблемами довольно быстро.
Ответ 7
Каждая нормальная операционная система (конечно, любая форма Linux или Windows) закрывает файлы, когда программа завершается. Если у вас очень простая программа, вам, вероятно, не нужно закрывать файлы при завершении. Однако закрытие файлов явно по-прежнему является хорошей практикой по следующим причинам:
-
если вы оставите его в ОС, у вас нет контроля над порядком, в котором файлы закрыты, что может привести к проблемам с согласованностью (например, в базе данных с несколькими файлами).
-
Если есть ошибки, связанные с закрытием файла (например, ошибки ввода-вывода, ошибки в пространстве и т.д.), вы не можете сообщить об этом.
-
могут быть взаимодействия с блокировкой файлов, которые необходимо обрабатывать.
-
процедура закрытия всех файлов может обрабатывать любую другую очистку, которая требуется программе в одно и то же время (например, буферы для очистки)