有必要多次使用fflush吗?

问题描述 投票:0回答:1

在APUE(UNIX环境下的高级编程)中,有很多

err_quit
err_sys
之类的。

例如

err_quit
的来源如下:

void err_quit(const char *fmt, ...) {
    va_list     ap;

    va_start(ap, fmt);
    err_doit(0, 0, fmt, ap);
    va_end(ap);
    exit(1);
}

static void err_doit(int errnoflag, int error, const char *fmt, va_list ap) {
    char    buf[MAXLINE];

    vsnprintf(buf, MAXLINE-1, fmt, ap);
    if (errnoflag)
        snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s",
          strerror(error));
    strcat(buf, "\n");
    fflush(stdout);     /* in case stdout and stderr are the same */  /* LINE A*/
    fputs(buf, stderr);
    fflush(NULL);       /* flushes all stdio output streams */        /* LINE B*/
}

我的问题是

LINE A
是必要的,因为
LINE B
的存在?我无法理解
LINE A
中的评论。

c linux unix fflush
1个回答
0
投票

此代码同时打印到

stdout
stderr
。当标准输出和标准错误流连接到同一管道或文件时,默认情况下它们是“完全缓冲”的,然后这些流的输出可能会混合。完全缓冲意味着流软件不会立即将输出发送到设备,而是将其内部记录在缓冲区中,并仅在缓冲区已满或请求刷新时才将其发送到设备。这样做是为了提高效率,因为它减少了处理输出所需的系统调用和 I/O 操作的数量。每个流都有一个单独的缓冲区。 例如,假设程序在调用此例程

stdout

之前向

err_doit
写入了一些文本,可能是文本
Continuing program operations, everything is good.\n
,然后调用
err_doit
并将
Error, the deaggregating fluxinator reported a zizzification error.\n
写入两个
stderr
。没有
fflush
呼叫会发生什么:

当第一条消息写入
    stdout
  • 时,
    Continuing program operations,
    填满了缓冲区,因此流软件将完整的缓冲区发送到管道或文件。
    然后流软件将其余文本
  • everything is good.\n
  • 放入缓冲区。
  • err_doit
  • 被呼叫并写信
    Error, the deaggregating fluxinator reported a zizzification error.\n
    stderr
    当程序终止时,缓冲区将被刷新。也许先写入 
  • stderr
  • ,所以
    Error, the deaggregating fluxinator reported a zizzification error.\n
    stderr
    被发送到管道或文件。
    然后 
  • stdout
  • 被刷新,将
     everything is good.\n
    发送到管道或文件。
    
    
  • 结果是管道或文件接收到此文本:

Continuing program operations,Error, the deaggregating fluxinator reported a zizzification error. everything is good.

因此,用户最终会在管道或文件中看到破碎且混合的消息。那不是我们想要的。为了避免这种情况,程序在写入 
stdout

之前先刷新

stderr
,然后再刷新
stderr
。这确保管道或文件将接收:
Continuing program operations, everything is good.
Error, the deaggregating fluxinator reported a zizzification error.

当您在命令行运行程序并让标准输出和标准错误连接到终端时,您通常不会看到这一点。这是因为,当这些流连接到终端时,默认情况下它们是“行缓冲”的,这意味着程序将在内部记录输出,并且仅在缓冲区已满时将其发送到设备,换行符是写入,或者请求刷新。因此,每当程序写入包含换行符的行时,直到该字符的输出都会立即发送到终端。只要程序以换行符结束每个输出,就可以防止 
stdout

stderr 数据交织。

    

© www.soinside.com 2019 - 2024. All rights reserved.