输入输出缓冲(IO buffering)自C标准库(stdio)出现以来就存在。它的引入旨在提高读写操作的性能,因为访问磁盘或设备是一项耗时的操作,而缓冲可以减少其数量。
对缓冲机制的不理解可能导致意外的输入输出延迟、程序意外终止时数据丢失、多线程操作中的错误(特别是在stdout/stderr时),以及进程或系统之间的同步错误。
了解文件流可以是缓冲的、线性缓冲的或不安全缓冲的,使用强制刷新缓冲区的函数(fflush())、正确关闭文件(fclose()),以及合理组合stdin、stdout和stderr的工作非常重要。缓冲也取决于流的类型(例如,stdout在与终端关联的流中输出字符 时会刷新,但在文件中不一定会)。
代码示例:
#include <stdio.h> int main() { printf("Hello"); // sleep(10); // 在fflush之前不会有输出 fflush(stdout); // 立即将缓冲区输出到屏幕 return 0; }
关键特性:
fflush() — 手动刷新缓冲的主要工具可以依赖printf的输出立即出现在屏幕上吗?
不可以,如果输出不是到终端,而是到文件中 — 字符串在缓冲区未刷新或达到缓冲限制之前不会出现。即使在终端中,没有 的字符串也可能不会立即出现。使用fflush(stdout);可以立即输出。
如果调用fflush(stdin)会发生什么?
这在C标准中是未定义行为。某些编译器/平台可能会清空输入流的缓冲区,但这并不在标准中得到保证,这种做法不具可移植性并且潜在危险。
可以将printf和fprintf(stderr, ...)视为立即输出的等效吗?
不可以。标准输出(stdout)通常是完全缓冲或行缓冲,stderr根据标准始终是不安全缓冲的。这意味着,输出到stderr立即出现在屏幕上,而输出到stdout则不会。
fflush(stdin)来清空输入缓冲程序通过printf写入日志文件,但在崩溃时没有调用fflush(stdout)并且没有关闭文件。
优点:
缺点:
程序在每次重要日志记录后调用fflush(stdout),或者将关键消息写入stderr。
优点:
缺点: