为什么stdout缓冲?

时间:2016-06-23 12:04:01

标签: c libuv

我正在尝试学习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和其他地方所解释的那样?为什么我需要手动冲洗它?

3 个答案:

答案 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。