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

ele*_*uid 57 c file-io fopen fclose

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

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

Ada*_*eld 79

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

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

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

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

如果您的程序正常退出,C运行时将负责刷新所有打开的缓冲流.因此,如果您已将缓冲数据写入FILE*未刷新的数据,则会在正常退出时刷新.

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

  • 我猜想尽快,因为该缓冲区不是神奇的-程序为它分配了内存,并且当您的程序崩溃时,操作系统应释放该内存作为正常清理的一部分。 (2认同)

zwo*_*wol 13

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

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

当然有一些操作系统在异常终止时没有清理外部可见资源; 它往往与不执行"核心"和"用户"的代码和/或之间存在明显的用户空间"进程"之间的硬边界特权一起去,只是因为如果你没有这些边界也未必如此做安全在所有情况下.(例如,考虑一下如果你在MS-DOS中的开放文件表上写垃圾会发生什么,就像你完全能够做到的那样.)

  • @Peter:C99,§7.20.4.3,4:"接下来,刷新所有带有未写入缓冲数据的开放流,关闭所有打开的流,并删除tmpfile函数创建的所有文件." 请注意,这仅适用于常规(`exit`,`return` from`main`)终止,`_Exit`&co会发生什么.是实现定义的. (5认同)

Jon*_*ler 5

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

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


Pet*_*ter 0

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

  • 典型的现代操作系统至少可以做到这一点。我的理解是,在过去,如果应用程序没有正确退出,Windows 3.1 等会泄漏句柄。如今可能还有一些其他非常小的操作系统(也许是嵌入式系统)无法为您处理这个问题。 (2认同)