9

printf を使用して stdout にメッセージを送信するプログラムを C でコーディングしましたが、出力をファイルにリダイレクトするのに問題があります (bash から実行)。

私はもう試した:

./program argument >> program.out
./program argument > program.out
./program >> program.out argument
./program > program.out argument

いずれの場合も、ファイル program.out が作成されますが、空のままです。実行終了後のファイルサイズは 0 です。

プログラムの実行時にリダイレクトを省略した場合:

./program argument

次に、printf を使用して stdout に送信されたすべてのメッセージがターミナルに表示されます。

この方法で出力をリダイレクトしても問題ない他の C プログラムがあります。それはプログラム自体と関係がありますか?引数を渡して?どこで問題を探す必要がありますか?

C プログラムに関するいくつかの詳細:

  • stdin からは何も読み取らない
  • BSD インターネット ドメイン ソケットを使用します。
  • POSIX スレッドを使用します
  • sigaction を使用して、SIGINT シグナルに特別なハンドラ関数を割り当てます。
  • 多くの改行を標準出力に送信します(フラッシュする必要があると考えている人向け)

いくつかのコード:

int main(int argc, char** argv)
{
    printf("Execution started\n");
    do
    {        
        /* lots of printf here */
    } while (1);
    /* Code never reached */
    pthread_exit(EXIT_SUCCESS);
}
4

5 に答える 5

15

改行後のフラッシュは、端末に印刷する場合にのみ機能しますが、ファイルに印刷する場合は必ずしも機能しません。Google で簡単に検索すると、次のページに詳しい情報が表示されます: http://www.pixelbeat.org/programming/stdio_buffering/

「デフォルトのバッファリング モード」というタイトルのセクションを参照してください。

結局、いくつかの呼び出しを fflush(stdout) に追加する必要があるかもしれません。

setvbufを使用してバッファ サイズと動作を設定することもできます。

于 2009-02-01T00:34:51.057 に答える
6

バッファのフラッシュは通常、関数によって処理されます。この関数は通常、 from main()exit()によって暗黙的に呼び出されます。returnSIGINTを発生させてプログラムを終了しているのですが、デフォルトのSIGINTハンドラーはバッファーをフラッシュしないようです。

この記事を見てください: シグナル処理を単純化するためのデザインパターンの適用。この記事は主にC++ですが、2番目のセクションに便利なCの例があり、SIGINTを使用してプログラムを正常に終了する方法を示しています。

端末の動作がファイルと異なる理由については、UNIX環境のバッファリングに関するセクション5.4のStevensの高度なプログラミングを参照してください。彼はこう言った:

ほとんどの実装では、デフォルトで次のタイプのバッファリングが使用されます。標準エラーは常にバッファリングされません。他のすべてのストリームは、端末デバイスを参照している場合、ラインバッファリングされます。それ以外の場合は、完全にバッファリングされます。この本で説明されている4つのプラットフォームは、標準I / Oバッファリングの規則に従います。標準エラーはバッファリングされておらず、端末デバイスに開かれているストリームはラインバッファリングされ、他のすべてのストリームは完全にバッファリングされます。
于 2009-02-01T04:09:53.197 に答える
3

リダイレクトされたファイルの内容を確認するまでに、プログラムは終了しましたか? まだ実行中の場合、出力はチェーンのどこかにまだバッファリングされている可能性があるため、ファイルには表示されません。

それと、これまでに提供された他の回答とは別に、問題コードの代表的な例を示す時が来たと思います。難解な可能性が多すぎます。

編集

サンプル コードを見ると、比較的少量の印刷が発生している場合は、出力バッファーに引っかかっています。各書き込み後にフラッシュして、ディスクに確実に書き込まれます。通常、ページ サイズに相当する未書き込みのデータをそのままにしておくことができます。

フラッシュがない場合、すべてがディスク上にあることを確認できるのは、プログラムが終了するときだけです。そのような出力バッファはスレッドごとではなく、プロセスごとであるため、スレッドの終了でさえそれを行いません。

于 2009-02-01T00:40:06.507 に答える
0

提案:

  1. stderrもファイルにリダイレクトします。
  2. 出力ファイルのtail-fを試してください。
  3. ファイルを開き、ログをfprintfします(何が起こっているのかを理解するのに役立ちます)。
  4. std * FILEハンドルまたは1〜3個のファイル記述子の手動によるクローズ/複製/配管を検索します。
  5. 複雑さを軽減します。printfsが機能するまで、機能の大きな塊を切り取ります。それからそれが再び壊れるまでそれらを読んだ。原因コードを特定するまで続けます。
于 2009-02-01T05:13:20.400 に答える
0

記録のために、Perl では次のように使用します。

use IO::Handle;

flush STDOUT;
autoflush STDOUT;
于 2009-07-08T12:35:19.150 に答える