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

std*_*all 23 c coding-style file-descriptor

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

Dav*_*eri 16

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

请参阅此示例中的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)
Run Code Online (Sandbox Code Playgroud)

如您所见,它会引发内存泄漏

在某些情况下,您可以使用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;
}
Run Code Online (Sandbox Code Playgroud)

  • `fopen()`返回的`FILE`指针不是文件描述符.它是一个文件流,具有关联的缓冲区.因此,当你的程序从`main`返回而没有正确的`fclose()`调用时,你会忘记这个内存泄漏,就像valgrind所示.关于_file描述符的问题仍然没有答案. (5认同)
  • @PavelZhuravlev认为,你是对的,对不起 (2认同)

Pav*_*lev 10

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

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

你没有在你的问题中提到操作系统,但是应该从任何操作系统中预期这种行为.每当您的程序控制流交叉exit()return从中流出时main(),系统都有责任在流程后进行清理.

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

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


小智 5

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

不要依赖那个 从概念上讲,当进程终止时,您有责任释放分配的内存,关闭非标准文件描述符等。当然,每个健全的OS(甚至Windows)都将在您执行该进程后进行清理,但这并不是期望的。