You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何fdopen转换STDOUT_FILENO得到的流无法用fflush正常工作?

问题:fdopen转换STDOUT_FILENO后fflush无效的原因

原始现象

运行以下C代码:

printf("This is sentence 1. ");
write(STDOUT_FILENO, "This is sentence 2.\n", 20);

得到顺序颠倒的输出:

This is sentence 2.
This is sentence 1. 

原因是:printf属于标准IO库,会将数据写入用户空间缓冲区,延迟刷新到内核;而write是系统调用,直接写入内核空间缓存,因此输出顺序错乱。

有效解决方法

通过fflush(stdout)手动刷新标准输出的用户缓冲区,即可得到正确顺序:

printf("This is sentence 1. ");
fflush(stdout);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);

输出正常:

This is sentence 1. This is sentence 2.

无效的替代尝试

尝试用fdopen将STDOUT_FILENO转为文件流,再刷新该流,结果依然顺序错误:

FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);

输出仍为:

This is sentence 2.
This is sentence 1.

验证文件描述符关联

为确认STDOUT_FILENO与stdout的对应关系,用fileno转换验证:

int fd = fileno(stdout);
if(fd == STDOUT_FILENO)
    printf("fd == STDOUT_FILENO == %d\n", fd);

输出符合预期:

fd == STDOUT_FILENO == 1

原因解析

核心问题是:fdopen创建的是独立的标准IO流对象,和原有stdout流无关联。

printf写入的是stdout对应的用户缓冲区,而fflush(file)刷新的是fdopen新创建的流的缓冲区——这两个流虽共享底层文件描述符,但各自维护独立的用户空间缓冲区。你刷新的并非printf写入的缓冲区,因此stdout的数据仍会延迟输出,导致顺序错乱。

此外,重复将同一个文件描述符关联到多个标准IO流的做法本身存在风险,多个独立流的缓存会引发数据错乱或输出异常,属于不规范用法。

正确做法

若要通过流刷新,直接操作stdout即可,无需用fdopen重新创建流。若确实需要从文件描述符创建流,需确保后续所有IO操作都使用该新流,避免混用原有stdout与新流。

内容的提问来源于stack exchange,提问作者Ruthy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:54:33