如果我不在C程序中调用fclose()会怎么样?

首先,我知道用fopen()打开一个文件而不closures它是非常不负责任的,而且是不好的forms。 这只是好奇心,所以请幽默我:)

我知道,如果一个C程序打开一堆文件,并从不closures它们中的任何一个,最终fopen()将开始失败。 有没有其他副作用,可能会导致代码本身之外的问题? 例如,如果我有一个程序打开一个文件,然后退出而不closures它,这可能会导致运行该程序的人的问题? 这样的程序会泄漏任何东西(内存,文件句柄)? 一旦程序结束,是否可以再次访问该文件? 如果该计划连续运行多次,会发生什么?

只要你的程序正在运行,如果你保持打开文件而不closures它们,最可能的结果就是你将用尽你的进程可用的文件描述符/句柄,并试图打开更多的文件将最终失败。 在Windows上,这还可以防止其他进程打开或删除已打开的文件,因为默认情况下,文件以独占共享模式打开,以防止其他进程打开文件。

一旦你的程序退出,操作系统就会清理完毕。 它会closures所有在终止进程时保持打开状态的文件,并执行任何其他需要的清理(例如,如果文件被标记为delete-on-close,那么将会删除文件;请注意这种情况是平台-具体)。

但是,另一个需要注意的问题是缓冲数据 。 大多数文件stream在将数据写出到磁盘之前会缓冲内存中的数据。 如果您使用stdio库中的FILE*stream,则有两种可能性:

  1. 通过调用exit(3)函数或从main (隐式调用exit(3) )返回,您的程序正常exit(3)
  2. 你的程序exception退出; 这可以通过调用abort(3)_Exit(3) ,从信号/exception中死亡等。

如果你的程序正常退出,C运行库将负责清除所有打开的缓冲stream。 所以,如果你把缓冲的数据写入一个没有被刷新的FILE* ,它将在正常的退出时被刷新。

相反,如果你的程序exception退出,任何缓冲的数据都不会被刷新。 操作系统只是说:“哦,亲爱的我,你留下了一个文件描述符打开,我最好closures你的”当进程终止; 它不知道有一些随机数据位于内存中的某个地方,程序打算写入磁盘,但没有。 所以要小心。

C标准说,调用exit (或者等价地,从main返回)会导致所有打开的FILE对象被closures,如果通过fclose 。 所以这是非常好的,除了你放弃检测写错误的机会。

编辑:没有这样的保证exception终止( abort ,一个失败的assert ,收到一个信号,其默认行为是exception终止程序 – 请注意,不一定有任何这样的信号 – 和其他实现定义的手段)。 正如其他人所说,现代操作系统将清理所有外部可见资源,例如开放的操作系统级别的文件句柄。 但是, FILE在这种情况下可能不会被刷新。

当然有一些操作系统在exception终止时没有清理外部可见的资源。 它倾向于不执行“内核”和“用户”代码之间和/或不同用户空间“进程”之间的硬特权边界,因为如果你没有这些边界,就不可能安全地这样做在所有情况下。 (举个例子,如果你在MS-DOS的开放文件表上写垃圾,会发生什么情况,因为你完全可以做到这一点)。

假设你在控制下退出,使用exit()系统调用或从main()返回,那么冲洗后closures打开的文件stream。 C标准(和POSIX)要求这样做。

如果你退出控制(核心转储,SIGKILL)等,或者如果你使用_exit()_Exit() ,那么打开的文件stream不会被刷新(但是文件描述符最终会closures,假设一个类似POSIX的系统文件描述符 – 标准C不要求文件描述符)。 请注意_Exit()是由C99标准强制的,但是_exit()是由POSIX强制的(但是它们在POSIX系统上performance相同)。 请注意,文件描述符与文件stream是分开的。 请参阅有关_exit()的POSIX页面上“程序终止的后果”的讨论,以了解程序在Unix下终止时会发生什么情况。

当进程死亡时,大多数现代操作系统(特别是内核)将释放所有的句柄并分配内存。