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

时间:2011-11-17 23:26:12

标签: c file-io fopen fclose

首先,我知道用fopen()打开一个文件而不关闭它是非常不负责任和糟糕的形式。这只是纯粹的好奇心,所以请幽默我:)

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

4 个答案:

答案 0 :(得分:74)

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

一旦程序退出,操作系统将在您之后清理。它将关闭你在终止进程时打开的所有文件,并执行任何其他必要的清理(例如,如果文件被标记为delete-on-close,那么它将删除该文件;请注意那种东西是平台特异性)。

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

  1. 您的程序正常退出,可以通过调用exit(3)函数,也可以从main返回(隐式调用exit(3))。
  2. 你的程序异常退出;这可以通过调用abort(3)_Exit(3),从信号/异常中死亡等来实现。
  3. 如果你的程序正常退出,C运行时将负责刷新所有打开的缓冲流。因此,如果您缓存了写入未被刷新的FILE*的数据,则会在正常退出时刷新它。

    相反,如果您的程序异常退出,则任何缓冲的数据都将被刷新。操作系统只是说“哦,亲爱的,你把文件描述符打开了,我最好为你关闭”,当进程终止时;它不知道有一些随机数据存在于内存中,程序打算写入磁盘但没有。所以要小心。

答案 1 :(得分:12)

C标准表示,调用exit(或等效地从main返回)会导致所有打开的FILE对象按fclose关闭。所以这很好,除了你没有机会发现写错误。

编辑 异常终止(abort,失败assert,收到信号,其默认行为是异常终止程序 - 请注意,不一定有任何此类信号 - 以及其他实现定义的方法)。正如其他人所说,现代操作系统将清理所有外部可见资源,例如打开操作系统级文件句柄,无论如何;但是,在这种情况下,FILE可能被刷新。

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

答案 2 :(得分:4)

假设您在控制下退出,使用exit()系统调用或从main()返回,则在刷新后关闭打开的文件流。 C标准(和POSIX)要求这样做。

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

答案 3 :(得分:0)

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