76

まず、fopen() でファイルを開き、ファイルを閉じないというのは、恐ろしく無責任で悪い形式であることを認識しています。これはただの好奇心です。

C プログラムが多数のファイルを開き、それらのいずれも閉じない場合、最終的に fopen() が失敗し始めることを私は知っています。コード自体以外で問題を引き起こす可能性のあるその他の副作用はありますか? たとえば、1 つのファイルを開き、それを閉じずに終了するプログラムがある場合、そのプログラムを実行している人に問題が発生する可能性はありますか? そのようなプログラムは何か (メモリ、ファイル ハンドル) をリークしますか? プログラムが終了した後、そのファイルに再びアクセスする際に問題が発生する可能性はありますか? プログラムが連続して何度も実行されるとどうなるでしょうか?

4

4 に答える 4

100

プログラムが実行されている限り、ファイルを閉じずに開き続けると、プロセスで使用できるファイル記述子/ハンドルが不足し、さらにファイルを開こうとすると最終的に失敗する可能性が最も高くなります。Windows では、これにより、開いているファイルを他のプロセスが開いたり削除したりすることもできなくなります。これは、デフォルトでは、ファイルは他のプロセスが開くことを防ぐ排他的共有モードで開かれるためです。

プログラムが終了すると、オペレーティング システムがクリーンアップします。プロセスを終了するときに開いたままにしたファイルを閉じ、必要なその他のクリーンアップを実行します(たとえば、ファイルがクローズ時に削除とマークされている場合、ファイルを削除します。そのようなことはプラットフォームであることに注意してください-明確な)。

ただし、注意すべきもう 1 つの問題は、バッファリングされたデータです。ほとんどのファイル ストリームは、データをディスクに書き込む前にメモリにバッファリングします。FILE*stdio ライブラリのストリームを使用している場合、2 つの可能性があります。

  1. 関数を呼び出すか、 (暗黙的に を呼び出す)exit(3)から戻ることによって、プログラムは正常に終了しました。mainexit(3)
  2. プログラムが異常終了しました。abort(3)これは、またはの呼び出し_Exit(3)、シグナル/例外による終了などを介して行うことができます。

プログラムが正常に終了した場合、C ランタイムは、開いていたバッファリングされたストリームをフラッシュします。したがって、FILE*フラッシュされていない に書き込まれたデータをバッファリングした場合、通常の終了時にフラッシュされます。

逆に、プログラムが異常終了した場合、バッファリングされたデータはフラッシュされません。OS は、プロセスが終了すると、「ああ、ファイル記述子を開いたままにしました。それを閉じたほうがよいでしょう」と言うだけです。プログラムがディスクに書き込むつもりでしたが、書き込まなかったランダムなデータがメモリのどこかにあることはわかりません。そのため、注意してください。

于 2011-11-17T23:49:19.527 に答える
13

C標準では、呼び出すexit(または、同等に、から戻るmain)と、開いているすべてのFILEオブジェクトがのように閉じられfcloseます。したがって、書き込みエラーを検出する機会を失うことを除いて、これは完全に問題ありません。

編集:異常終了のそのような保証はありません(abort、失敗したassert、デフォルトの動作がプログラムを異常終了する信号の受信-必ずしもそのような信号がないことに注意してください-および他の実装定義の手段)。他の人が言っているように、最新のオペレーティングシステムは、開いているOSレベルのファイルハンドルなど、外部から見えるすべてのリソースをクリーンアップします。ただし、その場合、 FILEsはフラッシュされない可能性があります。

異常終了時に外部から見えるリソースをクリーンアップしなかったOSは確かに存在します。「カーネル」コードと「ユーザー」コードの間、および/または個別のユーザースペース「プロセス」の間のハード特権境界を強制しないことに伴う傾向があります。これらの境界がない場合、安全に実行できない可能性があるためです。すべての場合において。(たとえば、MS-DOSでオープンファイルテーブルにガベージを書き込むとどうなるかを考えてみてください。完全に実行できます。)

于 2011-11-17T23:42:45.890 に答える
5

exit()システムコールを使用するか、から戻ると、制御下で終了すると仮定するとmain()、開いているファイルストリームはフラッシュ後に閉じられます。C標準(およびPOSIX)はこれを義務付けています。

制御不能(コアダンプ、SIGKILL)などを終了した場合、またはまたはを使用し_exit()た場合_Exit()、開いているファイルストリームはフラッシュされません(ただし、ファイル記述子を備えたPOSIXのようなシステムを想定すると、ファイル記述子は閉じられます-標準Cはファイル記述子を義務付けない)。_Exit()これはC99標準で義務付けられていますが、POSIXで義務付けられていることに注意してください_exit()(ただし、POSIXシステムでも同じように動作します)。ファイル記述子はファイルストリームとは別のものであることに注意してください。_exit()Unixでプログラムが終了したときに何が起こるかを確認するには、POSIXページの「プログラム終了の結果」の説明を参照してください。

于 2011-11-17T23:43:27.987 に答える
0

プロセスが停止すると、最新のオペレーティングシステム(特にカーネル)はすべてのハンドルと割り当てられたメモリを解放します。

于 2011-11-17T23:28:24.770 に答える