当前位置: 首页 > 科技观察

那些奇怪的缓冲问题

时间:2023-03-20 23:20:34 科技观察

在上篇文章《不可不知的缓冲类型》中提到了三种缓冲类型,看起来很简单吧?今天我们就来看看如何修改这些默认的缓冲类型,以及在实践中可能遇到哪些问题。更改缓冲区类型上一篇文章提到了一些默认的缓冲区类型,例如:指向终端设备的流是行缓冲的,标准错误是无缓冲的,指向文件的流是全缓冲的……那么这些默认缓冲区类型如何修改?有几个函数可用于更改缓冲区类型:#includevoidsetbuf(FILE*stream,char*buf);voidsetbuffer(FILE*stream,char*buf,size_tsize);voidsetlinebuf(FILE*stream);intsetvbuf(FILE*stream,char*buf,intmode,size_tsize);参数说明如下:streamFILE*type,filepointerbufbufferpointermode缓冲模式,包括_IOFBF(fullbuffer),_IOLBF(linebuffer),_IONBF(withoutbuffer)sizeBuffersize这里有四个相关的函数,功能类似,只是修改的范围不同。在setbuf函数中,如果buf设置为NULL,则关闭缓冲;否则,它指向一个长度为BUFSIZ的缓冲区,并且它是行缓冲的。#include#includeintmain(void){setbuf(stdout,NULL);printf("bianchengzhuji");sleep(10);return0;}这里设置为无缓冲,就会buf和size参数被忽略。当设置为全缓冲区或行缓冲区时。如果buf为NULL,将使用具有适当长度的系统缓冲区,否则将使用用户定义的缓冲区。缓冲区设置就介绍到这里。fputs没有及时输出其实有了前面的基础之后,很多问题就迎刃而解了。看看下面的例子:#include#includeintmain(void){//setbuf(stdout,NULL);fputc('a',stdout);sleep(10);返回0;}比如你要输出一个字符,它会打印到终端,但是按照上面的方法,这个字符不会及时输出到终端,所以默认是linebuffered。打开注释行并将其设置为无缓冲。printf打印的日志没有输出。不知道大家有没有遇到过这样的情况。当你准备调试某个bug时,发现每次运行到某个地方,打印结束,然后就挂了,让你误以为程序已经执行完毕。打印结束。但是,有可能程序执行到最后,但是因为打印是行缓冲的,所以有一部分打印不出来。您可能没有使用换行符打印。这时候可以设置成无缓冲,或者在关键位置fflush,或者打印的时候记得加换行。fflush之后,文件还是丢了。看完前面的内容,是不是觉得豁然开朗?不要高兴得太早。上述措施并非一帆风顺。你可能会踏入哪些陷阱?文件内容写入后,fflush,内容也可用。然后,完成后,系统立即重置。重置后,文件内容仍然丢失。还是发现文件大小为0,文件丢失。如果您没有遇到过这样的问题,那么您需要特别注意。虽然之前的fflush等措施已经对buffer的内容进行了I/O操作,但是操作系统还是需要将文件系统的buffer写入磁盘,所以直接reset会导致文件丢失!我应该怎么办?可以使用:fsync/sync函数sync命令以上函数或命令强制将文件系统的缓冲区写入磁盘,但根据内容的大小不同,所用的时间也不同。