開発者がメモリ リークについて話しているように感じますが、それが何を意味するのかを尋ねると、多くの人はわかりません。これらの状況を防ぐために、いずれかを決定しましょう。
ウィキペディアの定義はありません...
メモリ リークの最良の定義は何 ですか? また 、それを防ぐ最善の方法は何ですか?
開発者がメモリ リークについて話しているように感じますが、それが何を意味するのかを尋ねると、多くの人はわかりません。これらの状況を防ぐために、いずれかを決定しましょう。
ウィキペディアの定義はありません...
メモリ リークの最良の定義は何 ですか? また 、それを防ぐ最善の方法は何ですか?
2つの定義があります(少なくとも私にとっては):
単純な定義:割り当てプロセスの実行中に、どのプロセスでも再度割り当てることができなくなった、到達不能なメモリの解放の失敗。これは、ほとんどの場合、GC (ガベージ コレクション) 手法を使用するか、自動ツールで検出することで解決できます。
微妙な定義:プログラムが正しく機能するために不要になった到達可能なメモリを解放しないこと。これは、自動化されたツールまたはコードに精通していないプログラマーによって検出することはほとんど不可能です。技術的にはリークではありませんが、単純なものと同じ意味があります。これは私だけの考えではありません。ガベージ コレクション言語で書かれているにもかかわらず、変更ログでメモリ リークの修正について言及しているプロジェクトに出くわすことがあります。
参照が失われたために使用できない割り当てられたメモリ。
定義: 割り当て後のメモリ解放の失敗。
メモリ リソースが割り当てられ、不要になった後に適切に解放されないプロセスは、多くの場合、不適切なコーディング プラクティスによって導入されます。
一部の言語には、それらを防ぐのに役立つ方法が組み込まれていますが、それらを回避する最善の方法は、コード実行パスとコード レビューを入念に観察することです。メソッドを短く、目的を絞ることで、リソースの使用範囲を厳密に保ち、シャッフルで迷子になりにくくなります。
コンピューター サイエンスでは、メモリ リークとは、コンピューター プログラムによる特定のタイプの意図しないメモリ消費であり、プログラムが不要になったときにメモリを解放できません。この状態は通常、プログラムのバグが原因で、不要になったメモリを解放できなくなったことが原因です。
メモリ リークを定義する方法は 2 つあります。
まず、データへの参照がなくなったときにデータが解放されない場合、そのデータには到達できません (破損したポインターがあるか、バッファーなどでデータを読み過ぎない限り)。基本的に、ヒープに割り当てられたデータを解放/削除しないと、使用できなくなり、単にメモリが浪費されます。
ポインターが失われても、データには引き続きアクセスできる場合があります。たとえば、ポインターを int に格納するか、ポインターへのオフセットを (ポインター演算を使用して) 格納する場合でも、元のポインターを取得できます。
この最初の定義では、データはガベージ コレクターによって処理されます。ガベージ コレクターは、データへの参照数を追跡します。
第 2 に、メモリが最後に使用されたときに解放/削除されていない場合、メモリは本質的にリークします。参照され、すぐに解放される可能性がありますが、そうしないのは誤りです。正当な理由があるかもしれませんが (たとえば、デストラクタに奇妙な副作用がある場合など)、それはプログラムの設計が悪いことを示しています (私の意見では)。
この 2 番目のタイプのメモリ リークは、ファイル IO を使用する小さなプログラムを作成するときによく発生します。ファイルを開き、データを書き込みますが、完了したら閉じないでください。FILE* はまだスコープ内にある可能性があり、簡単に閉じることができます。繰り返しますが、これを行うには何らかの理由 (他のプログラムによる書き込みアクセスのロックなど) があるかもしれませんが、私にとってはそれは設計が悪いことを示しています。
この 2 番目の定義では、データはガベージ コレクターによって処理されません。ただし、コンパイラー/インタープリターがそれがもはや使用されないことを認識できるほど賢く (または愚かで)、データを解放しても副作用が発生しない場合を除きます。
ここで与えられたすべての定義 (私がこれを書いた時点で、より良い回答が得られています) は、1 つの境界ケースに対処できていません。
作成時にメモリを割り当てるシングルトンがあり、このメモリは通常、現在の使用が完了していてもプログラムが実行されている限り保持され、将来の使用が行われるかどうかは不明です。これは通常、再作成のオーバーヘッドのために行われます。
「完了時に解放に失敗する」標準では、これはリークと見なされます。メモリがまだ使用されているため、リーク報告ツールがそのようなことをリークと呼んでいるのを見てきました。(実際、コードには、オブジェクトをクリーンアップできるコードが含まれていない場合があります。)
ただし、オブジェクトを再作成するコストがそれほど大きくない場合でも、コンパイラ ライブラリでこの性質のコードに遭遇したことがあります。
漏れるかどうか?
不要になったときに割り当て解除されず、「到達可能」でなくなったメモリ。たとえば、アンマネージ コードでは、"new" を使用してオブジェクトをインスタンス化しますが、それを使い終わったときに "delete" を使用しません (そして、ポインターが範囲外に出たなど)。
それらを防ぐ最善の方法は、おそらく、誰に尋ねるか、どの言語を使用しているかによって異なります。もちろん、ガベージ コレクションはそのための優れたソリューションですが、これに関連するオーバーヘッドが発生する可能性があります。これは、パフォーマンスが主な関心事でない限り、大した問題ではありません。ガベージ コレクションは、使用している言語によっては、常に利用できるとは限りません。
または、適切な削除および/またはデストラクタが配置されていることを確認できます。メモリ リークを検出する方法やツールも多数ありますが、これは使用している言語や IDE によって異なります。
メモリ リーク: 次のいずれかの前に不要になったメモリを解放できませんでした。
メモリ リークを防止する最善の方法: 不要になったらすぐにメモリを解放します。
メモリリークを防止/検出するためのいくつかのテクニックを次に示します。
メモリ消費の観点からアルゴリズムを検討してください。他の回答者は、メモリ リークのために割り当てられた項目へのポインタを失う必要がないという事実に言及しています。実装にポインタ バグが含まれていなくても、割り当てられたアイテムが実際に必要になった後もずっとそのアイテムを保持していると、実質的にメモリ リークが発生する可能性があります。
アプリケーションをプロファイリングします。Valgrind や Purify などのメモリ デバッガ ツールを使用して、リークを見つけることができます。
ブラックボックステスト。大規模なデータ セットをフィードした後、または長時間実行した後、コンパイルされたコードがどうなるかを確認してください。そのメモリ フットプリントが際限なく増加する傾向があるかどうかを確認します。
編集:この答えは間違っています。自分がよく知っていると思っていることについて、いかに誤解されやすいかを示す例として、これを残しておきます。私の間違いを指摘してくださった皆様、ありがとうございます。
メモリ リークは次のとおりです。 プログラミング エラー。ソフトウェアがシステムからメモリの一部を借りて使用し、終了時にシステムに戻すことができません。これは、システムが再起動されるまで、特定のメモリ チャンクを他のプログラムが使用できないことを意味します。このようなリークの多くは、使用可能なメモリをすべて使い果たし、システムが完全に役に立たなくなる可能性があります。
メモリ リークを防ぐには、RIIA を実践し、常にソフトウェアをテストしてください。このタスクに使用できるツールはたくさんあります。