简体   繁体   English

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

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

Firstly, I'm aware that opening a file with fopen() and not closing it is horribly irresponsible, and bad form. 首先,我知道用fopen()打开文件而不关闭文件是非常不负责任的,而且格式不好。 This is just sheer curiosity, so please humour me :) 这只是纯粹的好奇心,所以请逗我:)

I know that if a C program opens a bunch of files and never closes any of them, eventually fopen() will start failing. 我知道,如果C程序打开一堆文件并且从不关闭任何文件,最终fopen()将开始失败。 Are there any other side effects that could cause problems outside the code itself? 还有其他副作用可能导致代码本身之外的问题吗? For instance, if I have a program that opens one file, and then exits without closing it, could that cause a problem for the person running the program? 例如,如果我有一个程序可以打开一个文件,然后退出而不关闭它,那可能会对运行该程序的人造成问题吗? Would such a program leak anything (memory, file handles)? 这样的程序会泄漏任何东西(内存,文件句柄)吗? Could there be problems accessing that file again once the program had finished? 程序完成后,再次访问该文件是否会出现问题? What would happen if the program was run many times in succession? 如果该程序连续运行多次会发生什么?

As long as your program is running, if you keep opening files without closing them, the most likely result is that you will run out of file descriptors/handles available for your process, and attempting to open more files will fail eventually. 只要您的程序正在运行,如果您继续打开文件而不关闭它们,最有可能的结果是您将用完进程可用的文件描述符/句柄,并且尝试打开更多文件最终将失败。 On Windows, this can also prevent other processes from opening or deleting the files you have open, since by default, files are opened in an exclusive sharing mode that prevents other processes from opening them. 在Windows上,这还可以防止其他进程打开或删除您已打开的文件,因为默认情况下,文件以独占共享模式打开,从而阻止其他进程打开它们。

Once your program exits, the operating system will clean up after you. 程序退出后,操作系统将在您执行后清理。 It will close any files you left open when it terminates your process, and perform any other cleanup that is necessary (eg if a file was marked delete-on-close, it will delete the file then; note that that sort of thing is platform-specific). 它将在终止过程时关闭您打开的所有文件,并执行其他必要的清除操作(例如,如果将文件标记为“关闭时删除”,则它将删除该文件;请注意,这种事情是平台的) -具体)。

However, another issue to be careful of is buffered data . 但是,要注意的另一个问题是缓冲数据 Most file streams buffer data in memory before writing it out to disk. 大多数文件流在将数据写到磁盘之前都会在内存中缓冲数据。 If you're using FILE* streams from the stdio library, then there are two possibilities: 如果您正在使用来自stdio库的FILE*流,则有两种可能性:

  1. Your program exited normally, either by calling the exit(3) function, or by returning from main (which implicitly calls exit(3) ). 通过调用exit(3)函数或从main返回(隐式调用exit(3) ),程序可以正常exit(3)
  2. Your program exited abnormally; 您的程序异常退出; this can be via calling abort(3) or _Exit(3) , dying from a signal/exception, etc. 这可以通过调用abort(3)_Exit(3) ,死于信号/异常等来实现。

If your program exited normally, the C runtime will take care of flushing any buffered streams that were open. 如果您的程序正常退出,则C运行时将负责刷新所有打开的缓冲流。 So, if you had buffered data written to a FILE* that wasn't flushed, it will be flushed on normal exit. 因此,如果您缓冲的数据写入了未刷新的FILE* ,它将在正常退出时被刷新。

Conversely, if your program exited abnormally, any buffered data will not be flushed. 相反,如果程序异常退出,则不会刷新任何缓冲的数据。 The OS just says "oh dear me, you left a file descriptor open, I better close that for you" when the process terminates; 进程终止时,操作系统只是说“哦,亲爱的,您打开了文件描述符,我最好为您关闭文件描述符”。 it has no idea there's some random data lying somewhere in memory that the program intended to write to disk but did not. 它不知道程序中有一些随机数据位于内存中某个位置,而程序打算将其写入磁盘。 So be careful about that. 因此,请注意这一点。

The C standard says that calling exit (or, equivalently, returning from main ) causes all open FILE objects to be closed as-if by fclose . C标准说,调用exit (或等效地从main返回)会导致所有打开的FILE对象被fclose视情况关闭。 So this is perfectly fine, except that you forfeit the opportunity to detect write errors. 因此,这很好,只不过您放弃了检测写错误的机会。

EDIT: There is no such guarantee for abnormal termination ( abort , a failed assert , receipt of a signal whose default behavior is to abnormally terminate the program -- note that there aren't necessarily any such signals -- and other implementation-defined means). 编辑:对于异常终止,没有这样的保证( abort ,失败的assert ,收到其默认行为是异常终止程序的信号-请注意,不一定有任何此类信号-以及其他实现定义的方法)。 As others have said, modern operating systems will clean up all externally visible resources, such as open OS-level file handles, regardless; 正如其他人所说,现代操作系统将清除所有外部可见资源,例如开放OS级别的文件句柄。 however, FILE s are likely not to be flushed in that case. 但是,在这种情况下,很可能不会刷新FILE

There certainly have been OSes that did not clean up externally visible resources on abnormal termination; 当然,有些操作系统在异常终止时不会清除外部可见的资源。 it tends to go along with not enforcing hard privilege boundaries between "kernel" and "user" code and/or between distinct user space "processes", simply because if you don't have those boundaries it may not be possible to do so safely in all cases. 它往往与不执行“核心”和“用户”的代码和/或之间存在明显的用户空间“进程”之间的硬边界特权一起去,只是因为如果你没有这些边界也未必这样做安全在所有情况下。 (Consider, for instance, what happens if you write garbage over the open-file table in MS-DOS, as you are perfectly able to do.) (例如,考虑到如果您完全有能力在MS-DOS中的打开文件表上写入垃圾,会发生什么情况。)

Assuming you exit under control, using the exit() system call or returning from main() , then the open file streams are closed after flushing. 假设您在控制之下退出,使用exit()系统调用或从main()返回,则刷新后关闭打开的文件流。 The C Standard (and POSIX) mandate this. C标准(和POSIX)强制执行此操作。

If you exit out of control (core dump, SIGKILL) etc, or if you use _exit() or _Exit() , then the open file streams are not flushed (but the file descriptors end up closed, assuming a POSIX-like system with file descriptors - Standard C does not mandate file descriptors). 如果退出控制(核心转储,SIGKILL)等,或者使用_exit()_Exit() ,则打开的文件流不会被刷新(但是文件描述符最终会关闭,假设是类似POSIX的系统文件描述符-标准C不强制使用文件描述符)。 Note that _Exit() is mandated by the C99 standard, but _exit() is mandated by POSIX (but they behave the same on POSIX systems). 请注意, _Exit()由C99标准规定,但_exit()由POSIX规定(但它们在POSIX系统上的行为相同)。 Note that file descriptors are separate from file streams. 请注意,文件描述符与文件流是分开的。 See the discussion of 'Consequences of Program Termination' on the POSIX page for _exit() to see what happens when a program terminates under Unix. 请参阅POSIX页面上有关_exit()的“程序终止的后果”的讨论,以了解当程序在Unix下终止时会发生什么。

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

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

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