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

Это хорошая практика закрыть дескрипторы файлов при выходе

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

4b9b3361

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

  • если вы оставите его в ОС, у вас нет контроля над порядком, в котором файлы закрыты, что может привести к проблемам с согласованностью (например, в базе данных с несколькими файлами).

  • Если есть ошибки, связанные с закрытием файла (например, ошибки ввода-вывода, ошибки в пространстве и т.д.), вы не можете сообщить об этом.

  • могут быть взаимодействия с блокировкой файлов, которые необходимо обрабатывать.

  • процедура закрытия всех файлов может обрабатывать любую другую очистку, которая требуется программе в одно и то же время (например, буферы для очистки)