退出时关闭文件描述符是一个好习惯吗?[关闭]

问题描述 投票:0回答:7

如果由于某种原因,我发现程序中存在致命情况,并且我想退出并显示错误代码。 有时,致命错误的上下文超出了其他文件描述符的范围。

关闭这些文件描述符是一个好习惯吗?

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

c coding-style file-descriptor
7个回答
21
投票

POSIX编程经典指南《UNIX环境下的高级编程》指出:

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

您在问题中没有提到操作系统,但任何操作系统都应该出现这种行为。每当您的程序控制流从

exit()
穿过
return
main()
时,系统就有责任在流程结束后进行清理。

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

fd
的自动关闭呢?

因此,保持

fd
开放的唯一问题可能是编程风格问题。而且,就像使用
stdio
对象(即围绕系统提供的文件 I/O 构建的东西)一样,您可能会在 valgrinding 时收到(有些)令人迷失方向的警报。至于泄漏系统资源的危险,应该没有什么可担心的,除非你的操作系统实现确实有错误。


19
投票

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

参见 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;
}

7
投票

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

不要依赖它。从概念上讲,当进程终止时,释放分配的内存、关闭非标准文件描述符等是“你的责任”。当然,每个正常的操作系统(甚至 Windows)都会在进程结束后进行清理,但这并不是什么事情期待。


4
投票

    如果将其留给操作系统,您将无法控制文件关闭的顺序,这可能会导致一致性问题(例如在多文件数据库中)。
  1. 如果存在与关闭文件相关的错误(例如 I/O 错误、空间不足错误等),您无法报告它们。
  2. 可能需要处理与文件锁定的交互。
  3. 关闭所有文件的例程可以同时处理程序需要的任何其他清理(例如刷新缓冲区)

3
投票


3
投票
exit

或从

main
返回),所有打开的文件都将被关闭。但是,如果您的程序异常终止,例如由于使用了 NULL 指针,它被操作系统关闭,由操作系统来关闭文件。因此,最好确保文件在不再需要时关闭,以防意外终止。

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


0
投票

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> char *bin = NULL; char *_argv = NULL; char *_envp = NULL; void handler(void) { execve(bin, &_argv, &_envp); } int main (int argc, char **argv, char **envp) { bin = argv[0]; _argv = *argv; _envp = *envp; printf("program name: %s pid: %d\n", argv[0], getpid()); int fd = open(".", O_DIRECTORY); sleep(1); atexit(handler); return 0; }

在 WSL2 中使用 gcc 作为编译器进行测试。

© www.soinside.com 2019 - 2024. All rights reserved.