我正在尝试学习libuv
api并编写了以下测试:
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
void timer_cb(uv_timer_t* timer) {
int* i = timer->data;
--*i;
if(*i == 0) {
uv_timer_stop(timer);
}
printf("timer %d\n", *i);
//fflush(stdout);
}
int main() {
uv_loop_t* loop = uv_default_loop();
uv_timer_t* timer = malloc(sizeof(uv_timer_t));
uv_timer_init(loop, timer);
int i = 5;
timer->data = &i;
uv_timer_start(timer, timer_cb, 1000, 2000);
uv_run(loop, UV_RUN_DEFAULT);
printf("Now quitting.\n");
uv_close(timer, 0);
uv_loop_close(loop);
return 0;
}
运行时,在程序运行完毕之前不会显示任何输出,然后立即显示所有输出。如果我取消注释fflush
行,它会按预期工作,每2秒写一次。
有人可以向我解释一下吗?为什么stdout
在换行符后没有刷新,如here和其他地方所解释的那样?为什么我需要手动冲洗它?
答案 0 :(得分:13)
流缓冲是实现定义的。
每 7.21.3档案,C Standard的第3段:
当流是 unbuffered ,字符应尽快从源或目的地出现。否则字符 可以累积并传输到主机或从主机传输 环境作为一个块。当流是 完全缓冲,当填充缓冲区时,字符旨在作为块传输到主机环境或从主机环境传输。当一个 流是 行缓冲,字符用于在换行时作为块传输到主机环境或从主机环境传输 遇到了字符。此外,字符也是如此 当缓冲区时,作为块传输到主机环境 填充时,在无缓冲的流上请求输入时,或何时 在需要的行缓冲流上请求输入 从主机传输字符 环境。 支持这些特征是 实施定义的,可能会受到
setbuf
和。{setvbuf
函数。
缓冲的类型取决于您的实现,在您的示例中,您的实现显然不是行缓冲。
答案 1 :(得分:5)
没有严格的要求,stdout
是行缓冲的。它也可以完全缓冲(或根本不缓冲),在这种情况下\n
不会触发刷新流。
C11(N1570)7.21.3 / 7 档案:
最初打开时,标准错误流未完全缓冲; 标准输入和标准输出流是完全缓冲的,如果 并且只有当流可以被确定为不参考时 互动设备。
C11(N1570)5.1.2.3/7 程序执行:
交互设备的构成是实现定义的。
您可以尝试通过setvbuf
标准功能强制执行特定类型的缓冲。例如,要为stdout
设置行缓冲,您可以尝试使用:
setvbuf(stdout, buff, _IOLBF, size);
其中buff
被声明为size
元素的字符数组(例如1024)。
请注意,必须在对流执行的任何其他I / O操作之前调用setvbuf
。
答案 2 :(得分:1)
出于某种原因,您的系统决定您的stdout不是交互式的。你在做什么奇怪的重定向stdout或做一些奇怪的终端?您应该能够使用setbuf覆盖,或者您可以使用stderr而不是stdout。