如果在 C 程序中不调用 fclose()会发生什么?

首先,我知道用 fopen ()打开一个文件而不关闭它是非常不负责任的,也是不好的形式。这纯粹是出于好奇,所以请迁就我一下:)

我知道,如果一个 C 程序打开一大堆文件,但从未关闭其中的任何一个,最终 fopen ()将开始失败。是否还有其他副作用会导致代码本身之外的问题?例如,如果我有一个程序打开一个文件,然后退出而没有关闭它,这会对运行该程序的人造成问题吗?这样的程序会泄漏任何东西(内存、文件句柄)吗?一旦程序完成,是否存在再次访问该文件的问题?如果程序连续运行多次会发生什么?

55558 次浏览

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

C 标准说,调用 exit(或者,等效地,从 main返回)会导致所有打开的 FILE对象被关闭,就好像 fclose关闭了一样。所以这是完全没有问题的,除了你放弃了检测写错误的机会。

编辑: 对于 变态终止没有这样的保证(abort,一个失败的 assert,接收一个默认行为是异常终止程序的信号——注意不一定有任何这样的信号——和其他实现定义的方法)。正如其他人所说的,现代操作系统将清理所有的 外部可见资源,例如打开的 OS 级文件句柄; 然而,在这种情况下,FILE很可能被刷新为 没有

当然也有一些操作系统在异常终止时没有清理外部可见的资源; 它倾向于在“内核”和“用户”代码之间和/或在不同的用户空间“进程”之间没有强制执行硬特权边界,仅仅是因为如果你没有这些边界,它可能不是 有可能在所有情况下都能安全地做到这一点。(例如,考虑一下,如果在 MS-DOS 中通过打开的文件表写入垃圾,会发生什么情况,这是您完全能够做到的。)

假设您在控制下退出,使用 exit()系统调用或从 main()返回,那么打开的文件流在刷新后关闭。C 标准(和 POSIX)强制执行此操作。

如果您退出失控(核心转储,SIGKILL)等,或如果您使用 ABC0或 _Exit(),那么打开的文件流不刷新(但文件描述符最终关闭,假设 POSIX 类系统的文件描述符-标准 C 不强制文件描述符)。请注意,_Exit()是由 C99标准规定的,而 _exit()是由 POSIX 规定的(但它们在 POSIX 系统上的行为是相同的)。请注意,文件描述符与文件流是分开的。请参阅 _exit()的 POSIX 页面上关于“程序终止的后果”的讨论,以了解当程序在 Unix 下终止时会发生什么。

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

一旦您的程序退出,操作系统将在您之后进行清理。当它终止你的进程时,它会关闭你打开的所有文件,并执行任何其他必要的清理(例如,如果一个文件被标记为“关闭时删除”,它就会删除该文件; 请注意,这类事情是特定于平台的)。

然而,另一个需要小心的问题是 缓冲数据缓冲数据缓冲数据。大多数文件流在将数据写入磁盘之前在内存中缓冲数据。如果您使用来自 stdio 库的 FILE*流,那么有两种可能性:

  1. 程序通过调用 exit(3)函数或从 main返回(main隐式调用 exit(3))正常退出。
  2. 您的程序异常退出; 这可能是通过调用 abort(3)_Exit(3)、死于信号/异常等。

如果程序正常退出,C 运行时将负责刷新所有打开的缓冲流。因此,如果您缓冲了写入 FILE*但没有刷新的数据,那么它将在正常退出时刷新。

相反,如果您的程序异常退出,任何缓冲数据将 没有刷新。当进程终止时,操作系统只是说“哦,天哪,你忘了打开文件描述符,我最好关闭它”; 它不知道在内存中的某个地方有一些随机数据,程序本来想写到磁盘上,但是没有写到。所以小心点。