web-dev-qa-db-ja.com

最高のメモリリークの定義

私は開発者がメモリリークについて話しているように感じますが、彼らに尋ねると、多くの人は何を意味しているのかわかりません。これらの状況を防ぐために、どちらかを決めましょう。

ウィキペディアの定義はありません...

メモリリークの最良の定義は何ですか?それらを防ぐための最良の方法は何ですか?

43
ewakened

2つの定義があります(少なくとも私にとって):

単純な定義:unreachableメモリの解放に失敗しました。これは、割り当てプロセスの実行中に、どのプロセスでも再度割り当てることができません。これは主に、GC(ガベージコレクション)テクニックを使用するか、自動ツールで検出することで解決できます。

微妙な定義:reachableメモリを解放できないため、プログラムが正しく機能するために必要ではなくなりました。これは、自動化されたツールで、またはコードに精通していないプログラマーが検出することはほぼ不可能です。技術的にはリークではありませんが、単純なものと同じ影響があります。これは私自身の考えではありません。ガベージコレクションされた言語で書かれたプロジェクトに出くわす可能性がありますが、変更ログでメモリリークを修正することについては言及しています。

45
artificialidiot

参照が失われたために使用できない割り当て済みメモリ。

25
truppo

定義:割り当て後にメモリを解放できませんでした。

6

メモリリソースが割り当てられ、不要になったときに適切に解放されないプロセス。多くの場合、不適切なコーディングプラクティスによって導入されます。

一部の言語にはそれらを防ぐための組み込みの方法がありますが、それらを回避する最善の方法は、コード実行パスとコードレビューを注意深く観察することです。メソッドを短く、目的を限定することで、リソースの使用を厳密にスコープし、シャッフルで迷子になる可能性を減らすことができます。

5
Joseph Ferris

w:

コンピュータサイエンスでは、メモリリークは、プログラムが不要になったときにメモリの解放に失敗する、コンピュータプログラムによる特定のタイプの意図しないメモリ消費です。この状態は通常、プログラムのバグの結果であり、不要になったメモリを解放することができません。

2
Eugene Yokota

不要になったときに割り当て解除されず、「到達可能」でなくなったメモリ。たとえば、アンマネージコードで、 "new"を使用してオブジェクトをインスタンス化したが、それが完了したときに "delete"を使用しなかった場合(そして、ポインターがスコープ外になっているなど)。

それらを防ぐ最良の方法は、おそらくあなたが尋ねる人とあなたが使用している言語に依存します。もちろん、ガベージコレクションはそのための優れたソリューションですが、これに関連するオーバーヘッドがいくつかある可能性があります。これは、パフォーマンスが主な関心事でない限り、大した問題ではありません。使用している言語によっては、ガベージコレクションが常に利用できるとは限りません。

または、適切な削除やデストラクタが配置されていることを確認できます。メモリリークを検出する方法やツールもたくさんありますが、これは言語や使用しているIDE=によって異なります。

1
Matthew Groves

メモリリークを定義する方法は2つあります。

まず、データへの参照がなくなったときにデータが解放されない場合、そのデータには到達できません(破損したポインターがないか、バッファーなどでデータを超えて読み取っていない限り)。基本的に、ヒープに割り当てられたデータを解放または削除しないと、データは使用できなくなり、メモリを浪費するだけです。

ポインターが失われた場合でも、データにアクセスできる場合があります。たとえば、ポインターをintに格納したり、ポインターへのオフセットを(ポインター演算を使用して)格納したりしても、元のポインターを元に戻すことができます。

この最初の定義では、データへの参照の数を追跡するガベージコレクターによってデータが処理されます。

次に、最後に使用したときにメモリが解放または削除されないと、メモリが本質的にリークされます。それは参照される可能性があり、すぐに解放可能ですが、そうしないように間違いがありました。正当な理由があるかもしれませんが(たとえば、デストラクタが奇妙な副作用を持っている場合など)、それは(私の意見では)悪いプログラム設計を示しています。

この2番目のタイプのメモリリークは、ファイルIOを使用する小さなプログラムを書くときによく起こります。ファイルを開いてデータを書き込みますが、完了したら閉じないでください。 FILE *はまだスコープ内にあり、簡単に閉じることができます。繰り返しますが、これには理由があります(他のプログラムによる書き込みアクセスをロックするなど)が、私にはそれは悪い設計のフラグです。

この2番目の定義では、コンパイラー/インタープリターがスマート(またはダム)でデータが使用されなくなることを知らない限り、ガベージコレクターはデータを処理しません。これにより、データを解放しても副作用は発生しません。

1
strager

メモリリーク:次のいずれかを行う前に、不要になったメモリを解放できません。

  • プログラムは終了します
  • 追加のメモリが割り当てられます

メモリリークを防止する最善の方法:不要になったメモリをすぐに解放します。

1
Robert Gamble

ここで与えられたすべての定義(私がこれを書いた時点で、それ以来より良い答えを得ています)は、1つの境界線のケースに対処できませんでした。

作成時にメモリを割り当てるシングルトンがあり、このメモリは通常、現在の使用が行われていて将来の使用が行われるかどうかが不明であっても、プログラムが実行されている限り保持されます。これは通常、再作成のオーバーヘッドのために行われます。

「それが終わったときに解放に失敗する」標準では、これはリークと見なされ、メモリがまだ使用されているため、リーク報告ツールがそのようなものをリークと呼ぶのを見てきました。 (実際、コードにはオブジェクトをクリーンアップできるコードが含まれていない場合があります。)

ただし、オブジェクトを再作成するコストがそれほど高くない場合でも、コンパイラライブラリでこのようなコードに遭遇しました。

漏れるかどうか?

1
Loren Pechtel

メモリリークを防止/検出するためのいくつかのテクニックを次に示します。

  1. メモリ消費の観点からアルゴリズムを検討してください。他の回答者は、メモリをリークするために割り当てられたアイテムへのポインターを失う必要がないという事実を述べています。実装にゼロポインターバグが含まれている場合でも、実際にそれらが必要になった後も、割り当てられたアイテムを長く保持していると、メモリリークが発生する可能性があります。

  2. アプリケーションのプロファイルを作成します。ValgrindやPurifyなどのメモリデバッガツールを使用して、リークを見つけることができます。

  3. ブラックボックステスト。大きなデータセットをフィードした後、または長期間実行した後のコンパイル済みコードの動作を監視します。そのメモリフットプリントが無制限に拡大する傾向があるかどうかを確認します。

1
mseery