C语言程序如果不关闭打开的文件,会发生什么?为什么要调用fclose() 函数?

在C语言程序开发中,有时需要读写一些文件,对于这样的需求,标准库提供了 fopen(),fread(),fwrite(),fclose() 等函数。以读取 story.txt 文件为例,C语言代码可以按照下面这样写:

FILE *fp = fopen("story.txt", "r");
fread(buf, size, nmemb, fp);
fclose(fp);

应注意,这里为了讨论主题,代码并未加入错误检查处理。在C语言程序中,读写文件的基本流程是确定的,即:

打开文件->读写文件->关闭文件

不过不知道读者想过没有,调用 fclose() 关闭文件的目的是什么呢?如果不关闭文件,会发生什么?

为什么要调用 fclose() 关闭文件?

“文件”显然由文件系统管理,而如今大多主流的文件系统都由操作系统管理。一般来说,操作系统使用描述符记录打开文件的资源,fopen() 函数则是用于创建描述符的,它返回的 FILE * 指针指向的就是描述符,而 fclose() 的作用则是释放这些描述符,毕竟描述符也是会消耗系统资源的。

显然,如果不调用 fclose() 函数关闭打开的文件,描述符将残留在系统中,直到程序终止运行才会被系统回收。

当然了,要是在C语言程序中,需要频繁的调用 fopen() 函数重复打开同一个文件,如果没有调用 fclose() 函数,随着C语言程序的运行,将会有越来越多的描述符泄漏。等达到一定的次数后,再调用 fopen() 函数,操作系统要么拒绝,要么无法创建文件描述符,此时 fopen() 函数就无法成功执行了,只能返回错误码。

此外,fwrite() 函数一般并不直接将数据写入磁盘,而是暂时将数据放在缓冲里,等到时机合适时,缓冲里的数据才会被真正写入磁盘。调用 fclose() 函数能够确保缓冲里的数据真正写入磁盘,防止C语言程序意外终止时丢失数据。

如果不调用 fclose() 函数会发生什么?

现在稍稍多考虑一些,如果我们编写了一段C语言程序,它调用 fopen() 函数打开了若干个文件,在退出之前没有调用 fclose() 函数关闭这些文件,会有内存泄漏吗?别的程序还能使用这些文件吗?

正如前面讨论的,只要C语言程序还在运行,如果持续的打开文件而又不关闭,最可能的结果是当前进程的文件描述符被用完,再调用 fopen() 函数就会失败,在 Windows 上,还会影响其他进程使用被占用的文件,因为默认情况下,文件是以独占模式被打开的,这样其他进程就无法打开这些文件了。

不过,一旦C语言程序结束运行,绝大多数现代操作系统都会回收程序相关的资源,包括打开的文件,这一点可参考我之前介绍 Linux 系统的文章。

这里还要强调下,一般来说,C语言标准库函数 fwrite() 并不直接将数据写入磁盘,而是暂时放在缓冲里,稍后才真正写入磁盘。如果C语言程序正常退出,在退出之前,缓冲内的磁盘数据将会被安全的写入磁盘。要是C语言程序没有调用 fclose() 函数,并且异常退出了,虽然操作系统仍然会回收文件描述符等资源,但是缓冲内残留的磁盘数据就丢失了。

小结

C语言程序调用 fclose() 函数关闭打开的文件,可以避免文件被长时间占用,也可以避免不再使用的文件占用程序资源,同时还可以最大程度的避免丢失数据。当然了,也可以搭配使用 fwrite() 函数和 fflush() 函数确保数据写入磁盘,不过频繁的调用 fflush() 函数会影响数据的写入效率,关闭不再使用的文件始终是有好处的。

https://stackoverflow.com/questions/8175827/what-happens-if-i-dont-call-fclose-in-a-c-program

阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif