1. ホーム
  2. c

[解決済み] 出力がファイルにリダイレクトされるとき、printf()とsystem()の結果が間違った順番になる [duplicate] 。

2022-12-17 05:48:11

質問

私はmyprogramという実行ファイルにコンパイルされるCプログラムを持っています。これはそのメイン関数です。

int main(int argc, char ** argv) {
  printf("this is a test message.\n");
  system("ls");

  return 0;
}

を実行すると myprogram > output.txt を Linux シェルで実行し、output.txt を調べると、出力は ls の上に記載されている "this is a test message."

と表示されるのですが、逆であるべきな気がします。なぜこのようなことが起こるのでしょうか。また、どうすれば "this is a test message" が output.txt の一番上に表示されるようになるのでしょうか。

重要であれば、私は C 言語とコマンドラインでの作業の両方が初めてです。

どのように解決するのですか?

デフォルトの出力先 stdout ラインバッファリング であり、ターミナルに接続されているときは つまり、バッファが一杯になったときや、改行を追加したときにバッファをフラッシュします。

しかし もし stdout がターミナルに接続されていない場合、例えば、プログラムの出力をファイルにリダイレクトするような場合は stdout フルバッファリング . つまり、バッファは満杯になったときか、明示的にフラッシュされたとき(プログラムが終了したときに起こる)、フラッシュされ実際に書き込まれます。

これは、あなたのコードから開始された別のプロセスの出力 (たとえば system を呼び出したときのような)別のプロセスの出力が最初に書かれる可能性が高いということです。なぜなら、そのプロセスのバッファはそのプロセスが終了したときにフラッシュされ、自分のプロセスよりも先になるからです。

リダイレクト(またはそのためのパイプ)を使用するとどうなるか。

  1. あなたの printf の呼び出しは stdout バッファに書き込みます。
  2. system 関数は新しいプロセスを開始し、それ自身のバッファに書き込みを行います。
  3. 外部プロセス(あなたの system によって起動された) 外部プロセスが終了すると、そのバッファはフラッシュされ、書き込まれます。あなた自身のプロセス内のあなた自身のバッファは触れません。
  4. 自分自身のプロセスが終了し、自分の stdout バッファがフラッシュされ、書き込まれます。

正しい(あるいは少なくとも期待される)順序で出力を得るには、次のように呼び出します。 fflush を呼び出す前に system を呼び出す前に、明示的にフラッシュする必要があります。 stdout を呼び出すか、あるいは setbuf を呼び出すと、バッファリングを完全に無効にすることができます。