繁体   English   中英

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

[英]What happens if I don't call fclose() in a C program?

首先,我知道用fopen()打开文件而不关闭文件是非常不负责任的,而且格式不好。 这只是纯粹的好奇心,所以请逗我:)

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

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

程序退出后,操作系统将在您执行后清理。 它将在终止过程时关闭您打开的所有文件,并执行其他必要的清除操作(例如,如果将文件标记为“关闭时删除”,则它将删除该文件;请注意,这种事情是平台的) -具体)。

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

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

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

相反,如果程序异常退出,则不会刷新任何缓冲的数据。 进程终止时,操作系统只是说“哦,亲爱的,您打开了文件描述符,我最好为您关闭文件描述符”。 它不知道程序中有一些随机数据位于内存中某个位置,而程序打算将其写入磁盘。 因此,请注意这一点。

C标准说,调用exit (或等效地从main返回)会导致所有打开的FILE对象被fclose视情况关闭。 因此,这很好,只不过您放弃了检测写错误的机会。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM