将stdout和stderr重定向至不同进程:C程序stdout无输出问题
问题分析与解决
为什么stderr无需fflush就能输出?
C标准库中stdout和stderr的默认缓冲策略存在差异:
stderr默认采用无缓冲(部分实现为行缓冲),所有写入操作会立即输出到目标设备,不需要手动调用fflush。stdout在连接终端时是行缓冲(遇到换行符自动刷新),但当它被重定向到管道时,会自动切换为全缓冲——只有缓冲区被填满或程序退出时才会刷新输出。你的程序循环输出但未填满缓冲区,导致stdout内容一直滞留在缓冲里,无法被后续sed进程读取。
无需手动插入fflush的解决办法
1. 代码中修改stdout的缓冲模式
在程序开头添加代码,将stdout设置为无缓冲或行缓冲:
- 设置无缓冲(和
stderr行为一致):
#include <stdio.h> int main() { setvbuf(stdout, NULL, _IONBF, 0); // 关闭stdout缓冲 while (1) { fprintf(stdout, "stdout: sias\n"); fprintf(stderr, "stderr: cias\n"); sleep(5); } return 0; }
- 设置行缓冲(你的输出每行带
\n,换行时自动刷新):
setvbuf(stdout, NULL, _IOLBF, 0); // 将stdout设为行缓冲
2. 用stdbuf命令强制修改缓冲(无需改代码)
运行程序时通过stdbuf工具强制设置stdout的缓冲模式,比如行缓冲:
{ stdbuf -oL tss 2>&1 1>&3 3>&- | sed -u 's/^/err: /'; } 3>&1 1>&2 | sed -u 's/^/out: /'
-oL表示将stdout设为行缓冲,-o0可设为无缓冲,这种方式无需修改C代码,适合快速测试。
3. 编译时设置相关选项(兼容性有限)
部分编译器提供编译选项修改默认缓冲行为,比如GCC结合-D_GNU_SOURCE宏,但这种方式兼容性较差,不如前两种方法通用。
内容的提问来源于stack exchange,提问作者user180574
相关产品推荐
相关产品推荐

