入出力バッファリング(IOバッファリング)は、C言語の標準ライブラリ(stdio)が登場した時から存在しています。これは、読み書き操作のパフォーマンスを向上させるために導入されました。なぜなら、ディスクやデバイスへのアクセスは時間のかかる高コストな操作であり、バッファリングによりその回数を減らすことができるからです。
バッファリングの動作を理解していないと、入出力において予期しない遅延が発生したり、プログラムの異常終了時にデータが失われたり、複数のスレッドでの動作のエラー(特にstdout/stderrで)や、プロセスやシステム間の同期エラーが生じる可能性があります。
ファイルストリームがバッファリングされている、行ごとにバッファリングされている、またはバッファリングされていないことを知っておくことは重要です。fflush()を使ってバッファを強制的にフラッシュし、ファイルを適切に閉じる(fclose())、stdin、stdout、およびstderrの扱いをうまく組み合わせる必要があります。バッファリングもストリームの種類(例えば、stdoutは関連する端末ストリームで を出力したときにフラッシュされますが、ファイルではそうならないことがあります)によって異なります。
コード例:
#include <stdio.h> int main() { printf("Hello"); // sleep(10); // fflushが呼ばれるまで出力されません fflush(stdout); // 即座にバッファを画面に表示します return 0; }
主な特徴:
fflush()は手動でバッファをフラッシュするための主要なツールです。printfの出力はすぐに画面に表示されると期待できますか?
いいえ、出力が端末ではなく、例えばファイルに送られる場合、バッファのフラッシュが行われるか、バッファの制限に達するまで行は表示されません。端末でも、 がない行はすぐに表示されないことがあります。即時出力にはfflush(stdout);を使用してください。
fflush(stdin)を呼び出すと何が起こりますか?
これはC標準における未定義の動作です。一部のコンパイラ/プラットフォームでは、入力ストリームのバッファをクリアすることがありますが、これは標準によって保証されておらず、この手法は移植性がなく、潜在的に危険です。
printfとfprintf(stderr, ...)は即時出力のために等価と見なせますか?
いいえ。標準出力(stdout)は通常、完全または行ごとにバッファリングされますが、stderrは標準で常に非バッファリングです。つまり、stderrへの出力はすぐに画面に表示されますが、stdoutへの出力はそうではありません。
fflush(stdin)を使用するプログラムがprintfを介してログファイルに書き込むが、fflush(stdout)を呼ばず、異常終了時にファイルを閉じない。
利点:
欠点:
プログラムが重要なログエントリの後にfflush(stdout)を呼び出すか、stderrに重要なメッセージを書き込む。
利点:
欠点: