C -在退出时关闭文件描述符是一个好做法吗?



如果由于某种原因,我发现程序中出现了致命的情况,并且我想用错误代码退出。有时,致命错误的上下文在其他文件描述符的范围之外。关闭这些文件描述符是个好做法吗?据我所知,当进程结束时,这些文件会自动关闭。

经典POSIX编程指南" UNIX环境中的高级编程"说明:

当一个进程终止时,内核会自动关闭它所有打开的文件。许多程序利用了这一点,不显式地关闭打开的文件。

你没有在你的问题中提到操作系统,但是这样的行为应该是任何操作系统所期望的。当你的程序控制流从main()跨越exit()return时,系统有责任在处理后进行清理。

在操作系统实现中总是存在bug的危险。但是,另一方面,在进程结束时,系统必须释放的内存远不止几个打开的文件描述符:可执行文件映像、堆栈、与进程相关的内核对象所占用的内存。您不能从用户空间控制这种行为,您只能依赖它按预期工作。那么,为什么程序员不能依赖于fd的自动关闭呢?

所以,留下fd s的唯一问题可能是编程风格的问题。而且,在使用stdio对象(即围绕系统提供的文件i/o构建的东西)的情况下,您可能会在valgrind(在某种程度上)收到令人迷惑的警报。至于泄漏系统资源的危险,应该没什么好担心的,除非你的操作系统实现真的有bug。

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

参见本例中的valgrind

david@debian:~$ cat demo.c
#include <stdio.h>
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 <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;
}

据我所知,当进程结束时,这些文件将自动关闭。

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

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

每个相同的操作系统(当然是任何形式的Linux或Windows)都会在程序终止时关闭文件。如果你有一个非常简单的程序,那么你可能不需要在终止时关闭文件。然而,由于以下原因,显式关闭文件仍然是一种良好的做法:

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

  2. 如果有与关闭文件相关的错误(如I/O错误,空间不足错误等),您无法报告它们。

  3. 可能有需要处理的文件锁定交互

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

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

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

相关内容

  • 没有找到相关文章

最新更新