ガベージ コレクションが良いことかどうかをめぐる聖戦では、ファイル ハンドルの解放などを処理しないと指摘されることがよくあります。このロジックをファイナライザーに配置することは、リソースが非決定論的に解放されるため、悪いことと見なされます。ただし、簡単な解決策は、OS が大量のファイルハンドルを利用できるようにすることです。これにより、それらが安価で豊富なリソースになり、いつでもいくつかを無駄にすることができます。なぜこれが実際に行われていないのですか?
6 に答える
実際には、OSは、さまざまなプロセスで使用されているハンドルを追跡するために、より多くのメモリオーバーヘッドを割り当てる必要があるため、これを行うことはできません。以下に示すCコードの例では、例として循環キューに格納された単純なOSプロセス構造を示します...
struct ProcessRecord { int ProcessId; CPURegs cpuRegs; TaskPointer**子供; int * baseMemAddress; int sizeOfStack; int sizeOfHeap; int * baseHeapAddress; int粒度; int時間; enum State {Running、Runnable、Zombie ...}; /*...ここにさらにいくつかのフィールドがあります...*/ long * fileHandles; long fileHandlesCount; } proc;
fileHandlesが整数の配列へのポインタであり、各整数には、ファイルがディスク上に格納されているOSのテーブルへのオフセットの場所(おそらくエンコードされた形式)が含まれていると想像してください。
ここで、どれだけのメモリを消費し、カーネル全体の速度を低下させる可能性があるかを想像してください。使用中のファイルハンドルの量を追跡する必要がある結果として、システムの「マルチタスク」の概念が崩壊するため、不安定になる可能性があります。また、整数へのポインタを動的に増減するメカニズムを提供します。これは、OSがユーザープログラムの要求に基づいてファイルハンドルをディッシュアウトしている場合に、ユーザープログラムの速度を低下させる効果があります。
これが、なぜそれが実装されておらず、実用的でもないのかを理解するのに役立つことを願っています。
これが理にかなっていることを願っています、よろしく、トム。
ファイル ハンドルの量だけではありません。一部のモードで使用されると、他の呼び出し元が同じファイルにアクセスできなくなることがあります。
ファイルを閉じると、ディスクへの書き込みもフラッシュされます-とにかく、アプリケーションの観点からはそうです。ファイルを閉じた後、アプリケーションがクラッシュする可能性がありますが、システム自体がクラッシュしない限り、変更は失われません。そのため、GC が余暇にファイルを閉じられるようにするのは得策ではありません。今の時代なら技術的に可能かもしれませんが。
また、実を言うと、古い習慣はなかなか消えません。ファイル ハンドルは以前は高価でしたが、歴史的な理由から、今でも高価であると考えられています。
より包括的な回答が得られると確信していますが、Windows の基本的な操作に関する私の限られた経験と理解に基づいて、ファイル ハンドル (OS に対してそれらを表すために使用される構造) はカーネル オブジェクトであり、そのため、特定のタイプのメモリが利用可能であること - 同じリソース (つまりファイル) へのアクセスを必要とする複数のプロセスとの一貫性と一貫性を維持するためのカーネル部分での処理は言うまでもありません
それらが必ずしも高価であるとは思いません.アプリケーションがいくつかの不必要なものしか開いていない場合、システムを殺すことはありません. C++ でいくつかの文字列だけをリークしても、かなり注意深く見ない限り、誰も気付かないのと同じです。問題になるのは次の場所です。
- 何百、何千と漏らしたら
- ファイルを開いていると、そのファイルで他の操作を実行できない場合 (他のアプリケーションでファイルを開いたり削除したりできない場合があります)
- それはずさんさのしるしです。あなたのプログラムが所有しているもの、使用しているもの、または使用を停止したものを追跡できない場合、プログラムには他にどのような問題がありますか? 何か小さな変化があったり、ユーザーが以前とは少し違うことをしたりすると、小さなリークが大きなリークに変わることがあります。
Linux パラダイムでは、ソケットはファイル記述子です。TCP ポートをできるだけ早く解放することには明確な利点があります。