在退出时关闭文件描述符是一个好习惯

如果由于某种原因,我发现程序中有致命的情况,我想退出错误代码。 有时,致命错误的上下文超出了其他文件描述符的范围。 关闭这些文件描述符是一个好习惯。 据我所知,这些文件会在进程终止时自动关闭。

文件会自动关闭,但这是一个很好的做法。

请参阅此示例中的valgrind

 david@debian:~$ cat demo.c #include  int main(void) { FILE *f; f = fopen("demo.c", "r"); return 0; } david@debian:~$ 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  #include  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; } 

POSIX编程的经典指南“UNIX环境中的高级编程”指出:

当进程终止时,内核会自动关闭其所有打开的文件。 许多程序利用了这一事实,并没有明确关闭打开的文件。

你没有在你的问题中提到操作系统,但是应该从任何操作系统中预期这种行为。 每当程序控制流超过exit()或从main() return ,系统负责在进程后进行清理。

操作系统实施中总是存在错误的危险。 但是,另一方面,系统必须在进程终止时解除分配多个打开文件描述符的方式:可执行文件映像,堆栈,与进程关联的内核对象占用的内存。 您无法从用户空间控制此行为,只需依靠其按预期工作即可。 那么,为什么程序员不能依靠自动关闭fd

因此,将fd s打开的唯一问题可能是编程风格问题。 而且,就像使用stdio对象(即围绕系统提供的文件i / o构建的东西)一样,在valgrinding时你可能会(有些)迷惑警报。 至于泄漏系统资源的危险,应该没有什么可担心的,除非你的操作系统实现真的有缺陷。

据我所知,这些文件会在进程终止时自动关闭。

不要依赖于此。 从概念上讲,当进程终止时, 您有责任释放已分配的内存,关闭非标准文件描述符等。当然,每个理智的操作系统(甚至Windows)都会在您的进程后清理,但这不是我们所期望的。

是。 假设您的主程序现在是一个单独程序中的类。 现在您刚刚描述了资源泄漏。 你实际上是依赖于全局程序状态,即进程的状态 – 不是你的模块,不是类,不是ADT,不是线程,而是整个进程 – 处于关闭状态,从而违反了封装。

如果你的程序正常终止(即通过exit或从main返回),C确保所有打开的文件都将被关闭。 但是,如果程序exception终止,例如由于使用NULL指针而被操作系统关闭,则由操作系统关闭文件。 因此,如果文件在意外终止时不再需要,请确保文件已关闭。

另一个原因是资源限制。 大多数操作系统都限制打开的文件数量(以及许多其他内容),因此最好在不再需要这些资源时立即返回这些资源。 如果每个程序都无限期地打开所有文件,那么系统很快就会遇到问题。

每个理智的操作系统(当然任何forms的Linux或Windows)都会在程序终止时关闭文件。 如果你有一个非常简单的程序,那么你可能不需要在终止时关闭文件。 但是,明确关闭文件仍然是一种很好的做法,原因如下:

  1. 如果将其保留在操作系统中,则无法控制文件关闭的顺序,这可能会导致一致性问题(例如在多文件数据库中)。

  2. 如果存在与关闭文件相关的错误(例如I / O错误,空间错误等),则无法报告它们。

  3. 可能存在需要处理的文件锁定交互。

  4. 关闭所有文件的例程可以处理程序同时需要的任何其他清理(例如,刷新缓冲区)