Если по какой-то причине я обнаружил фатальную ситуацию в моей программе, и мне бы хотелось выйти с кодом ошибки. Иногда контекст фатальной ошибки выходит за рамки других дескрипторов файлов. это хорошая практика для закрытия этих файловых дескрипторов. Насколько я знаю, эти файлы автоматически закрываются, когда процесс умирает.
Это хорошая практика закрыть дескрипторы файлов при выходе
Ответ 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) закрывает файлы, когда программа завершается. Если у вас очень простая программа, вам, вероятно, не нужно закрывать файлы при завершении. Однако закрытие файлов явно по-прежнему является хорошей практикой по следующим причинам:
-
если вы оставите его в ОС, у вас нет контроля над порядком, в котором файлы закрыты, что может привести к проблемам с согласованностью (например, в базе данных с несколькими файлами).
-
Если есть ошибки, связанные с закрытием файла (например, ошибки ввода-вывода, ошибки в пространстве и т.д.), вы не можете сообщить об этом.
-
могут быть взаимодействия с блокировкой файлов, которые необходимо обрабатывать.
-
процедура закрытия всех файлов может обрабатывать любую другую очистку, которая требуется программе в одно и то же время (например, буферы для очистки)