当输出被重定向到一个文件时,printf()和system()的结果顺序会出错。
当输出被重定向到一个文件时,printf()和system()的结果顺序会出错。
这个问题已经有了答案:
我有一个编译成可执行文件名为myprogram的C程序,这是它的主函数:
int main(int argc, char ** argv) { printf("this is a test message.\n"); system("ls"); return 0; }
当我在Linux shell中运行myprogram > output.txt
,然后检查output.txt,我看到 ls
输出在“this is a test message”上方。
我觉得它应该是反过来的。为什么会发生这种情况,我该怎么做才能让“this is a test message”出现在output.txt的顶部呢?
如果有关系的话,我是新手,既不熟悉C,也不熟悉在命令行中工作。
admin 更改状态以发布 2023年5月23日
这与输出缓冲有关。我成功地复制了相同的行为。强制刷新对我有用。
#include#include int main(int argc, char ** argv) { printf("this is a test message.\n"); fflush(stdout); system("ls"); return 0; }
在添加fflush之前:
$ ./main > foo $ cat foo main main.c this is a test message.
之后:
$ ./main > foo $ cat foo this is a test message. foo main main.c
默认情况下,当连接到终端时,对于stdout的输出是按行缓冲。也就是说,当缓冲区满或添加换行符时,缓冲区将被刷新。
然而,如果stdout没有连接到终端,比如将程序的输出重定向到文件时,那么stdout将变成完全缓冲的。也就是说,缓冲区将被刷新并且实际上会在缓冲区满或显式刷新时写入(发生在程序退出时)。
这意味着从你的代码启动的一个单独的进程的输出(例如当你调用system
时发生的情况)很可能首先被写入,因为在该进程结束时,该进程的缓冲区将被刷新,而在你自己的进程之前。
使用重定向(或管道)时会发生什么:
- 你的
printf
调用写入stdout缓冲区。 system
函数启动一个新的进程,该进程写入自己的缓冲区。- 当外部进程(由你的
system
调用启动的进程)退出时,它的缓冲区将被刷新和写入。你自己进程中的缓冲区不会被处理。 - 你自己的进程结束,你的stdout缓冲区被刷新并写入。
为了按照“正确的”(或至少是预期的)顺序获取输出,请在调用system
之前调用fflush
,以显式刷新stdout,或在任何输出之前调用setbuf
以完全禁用缓冲。