そのため、libc の stdio 部分がどのように実装されているかを調べていて、別の質問に出くわしました。見るとman setvbuf
、次のように見えます。
ファイルに対して最初の I/O 操作が発生すると、malloc(3) が呼び出され、バッファが取得されます。
これは理にかなっていmalloc
ます。実際に使用しない限り、プログラムに I/O 用の を含めるべきではありません。これに対する私の直感的な反応は、libc がここで独自の混乱を解消するということです。これは、valgrind がメモリ リークを報告していないためだと思います (もちろん、何か汚いことをして、malloc
直接割り当てないこともできます... しかし、今のところ文字通り使用していると仮定しますmalloc
)。
ただし、独自のバッファも指定できます...
int main() {
char *p = malloc(100);
setvbuf(stdio, p, _IOFBF, 100);
puts("hello world");
}
いやいや、メモリリーク!valgrind はそれを確認します。そのため、stdio が独自にバッファーを割り当てるたびに、自動的に削除されるようです (遅くともプログラムの終了時ですが、おそらくストリームの終了時)。ただし、バッファーを明示的に指定する場合は、自分でクリーンアップする必要があります。
ただし、キャッチがあります。マニュアルページには次のようにも書かれています:
ストリームが閉じられるまでに buf が指す領域がまだ存在していることを確認する必要があります。これは、プログラムの終了時にも発生します。たとえば、次は無効です。
現在、これは標準ストリームにとって興味深いものになっています。それらはプログラムの終了時に閉じられるため、手動で割り当てられたバッファーをどのように適切にクリーンアップしますか? ファイル構造内で「フラグを閉じるときにこれをクリーンアップする」ことを想像できますが、これを正しく読むと次のようなことを行うため、毛むくじゃらになります。
setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");
次の文のために、標準ライブラリによって 2 つの割り当てが発生します。
引数 buf が NULL の場合、モードのみが影響を受けます。次の読み取りまたは書き込み操作で新しいバッファが割り当てられます。
編集:私の質問への補遺。free
に渡すバッファが必要であることは明らかなのでsetvbuf
、実際に使用する場合stdout
、実用的な方法はありますfree
か? プログラムの終了まで存続する必要があります。私が考えることができる最善の方法はfclose(stdout)
、一部の人が言及したように、それを解放するか、静的バッファーを使用することです。それは厄介な設計上の決定のように思えるので、私は尋ねます.