c - 关闭标准输出后调用 printf 会发生什么?

标签 c linux

我试过下面的代码,但屏幕什么也没显示。

close(STDOUT_FILENO); 
printf("Child output something\n");

难道只是找不到标准输出,然后中止数据?

我想看看 printf 是否写了一些数据,因为我无法打印返回值,所以我将它输出到某个文件。

close(STDOUT_FILENO); 
int res = printf("output something\n");
open("./log.output", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d", res);   // return 17

所以 printf 工作,但我不知道它写到哪里。

最佳答案

您看到此结果的原因与缓冲有关。通常,附加到终端的文件是行缓冲的,所有其他文件是 block 缓冲的。 stderr 是无缓冲的。

当您关闭标准输出时,它不再连接到终端,因此它是 block 缓冲的,而不是行缓冲的。您试图写入比缓冲区大小(通常是 512 的倍数)更少的字节,因此 printf 愉快地将它复制到缓冲区并且什么都不做。如果您使用 printf 写入了适当数量的数据,您会发现它确实在那一点上失败了。

您可以通过调用 fflush(stdout) 来验证类似的行为:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    close(STDOUT_FILENO);
    int res = printf("output something\n");
    fprintf(stderr, "%d\n", res);
    res = fflush(stdout);
    fprintf(stderr, "%d %s\n", res, strerror(errno));
}

最后一行将输出 -1 Bad file descriptor,这表明写入 stdout 的尝试如预期的那样因 EBADF 而失败。如果您需要验证数据是否已写入,则必须根据需要调用 fflushfsync

请注意,一般来说,您不想关闭三个默认文件描述符中的任何一个,因为任何时候您打开一个新的文件描述符,它都会使用最低的未使用数并取代其中一个标准流.如果您的程序的一个单独部分试图在不检查的情况下写入其中一个流,它可能会写入一个意外的文件,从而破坏它。安全的做法是将这些流重定向到 /dev/null

您对 log.outputopen 调用与我刚才提到的完全相同,它再次打开文件描述符 1 (stdout)。

关于c - 关闭标准输出后调用 printf 会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59094054/

相关文章:

c++ - C中关于除以零的一些事情

c - 为什么这样会产生无限循环(C,While Loop)

c - 单片机通过虚拟串口不断接收值 "255ld"

linux - 获取 nohup R 程序完成的时间

linux - 规避脚本中的参数列表太长(for 循环)

c - 简单的 list 。主文件中的规范(方法、结构)不会在单独的文件(h 和 c)中编译。为什么?

C:删除文件中所有出现的单词

linux - DejaGNU - 想要在整个测试过程中使用来自 Linux 的环境变量

linux - 使用 linux 命令删除和替换一行

linux - Bash 终端 - .profile 不调用终端中的某些函数