「放棄されたメモリ」が単一のオブジェクトではなく、リークされたオブジェクトグラフ全体を指すことを除いて、どちらもまったく同じです。右?
3 に答える
まず、「メモリ オブジェクト グラフ」または「アプリケーション オブジェクト グラフ」(または、割り当てられたバッファに適用されるため、単に「オブジェクト グラフ」) の概念を理解する必要があります。malloc()
この場合、「オブジェクト」は、オブジェクトであれ単純なed バッファーであれ、アプリケーション内の割り当てを指します。オブジェクトが他のオブジェクトへの参照 (ポインター) を含むことができる場合の「グラフ」部分。
アプリケーションの「ライブ オブジェクト グラフ」は、アプリケーション内のさまざまな「ルート」から直接的または間接的に到達できるすべての割り当てです。「ルート」とは、他の何かがルートを明示的に参照しているかどうかに関係なく、それ自体でオブジェクトへのライブ参照を表すものです。
たとえば、グローバル変数はルートです。グローバル変数は、オブジェクトを参照することにより、定義上、そのオブジェクトをアプリのライブ オブジェクト グラフの一部にします。また、暗黙的に、オブジェクトがグローバル変数によって参照されるすべてのオブジェクトもライブであると見なされます。漏れていません。
同じことがスタックにも当てはまります。スレッドのライブ スタックによって参照されるオブジェクトは、それ自体がライブと見なされます。
このことを念頭に置いて、リークと放棄されたメモリには、実際には 2 つの異なる意味があります。
リーク
リークは、アプリケーションのライブ オブジェクト グラフ内のライブ オブジェクトからの割り当てへの参照がないメモリの一部です。
つまり、メモリに到達できないため、再度参照することはできません (バグがなければ)。死んだ記憶です。
オブジェクト A がオブジェクト B を指し、オブジェクト B が A を指しているが、ライブ オブジェクト グラフに A または B のいずれも指していない場合でも、それはリークであることに注意してください。B->A および A->B 参照が両方とも保持された参照である場合、保持サイクルとリークが発生します。
捨てられた記憶
アプリのライブ オブジェクト グラフにあるが、アプリケーション ロジックの問題のために到達できなくなった割り当ては、放棄されたと見なされますが、リークはされません。
たとえば、NSData
ある URL からダウンロードされたインスタンスであるエントリを持つキャッシュがあり、その URL には URL にセッション ID が含まれており (一般的なパターン)、そのセッション ID + URL がキーとして使用され、その中のものを検索するとします。キャッシュ。ここで、ユーザーがログアウトすると、セッション ID が破棄されたとします。そのセッション ID に固有のすべてのエントリがキャッシュからプルーニングされていない場合、それらのNSData
オブジェクトはすべて破棄されますが、キャッシュ経由でアクセスできるため、リークは発生しません。
実際には、この 2 つの違いを明確にすることにはほとんど意味がありませんが、いずれかを修正するには非常に異なる戦略が必要です。
リークを修正することは、余分な保持がどこから来たかを把握することです (または、ベースリークfree()
の場合は、欠落している呼び出しを挿入する必要がある場所)。malloc()
検出されたリークはライブ オブジェクト グラフから到達できないため、リークの修正は実に簡単です。
放棄されたメモリを修正することは、いくつかの理由でかなりトリッキーになる可能性があります。
まず、ライブ オブジェクト グラフからメモリにアクセスできます。したがって、定義上、メモリを維持しているアプリケーションにはアルゴリズムの問題があります。多くの場合、単なるリークを修正するよりもはるかに困難で混乱を招く可能性があるものを見つけて修正します。
第 2 に、放棄された割り当てへのゼロ化されていない保持されていない弱参照が存在する可能性があります。つまり、どこで強い参照を削除し、割り当てを実際になくすかを判断したとしても、それで作業が完了したわけではありません。ゼロ化されていない弱い参照が残っている場合、それらはダングリング ポインターになり、.. BOOMになります。
Amit が示したように、ヒープショット分析は、リーク、放棄されたメモリ、そして非常に重要な全体的な「望ましくないメモリの増加」の両方を見つけるのに非常に優れています。
標準的な用語があるかどうかはわかりませんが、参照はあるが使用されないメモリが存在する可能性もあります。(Leaks インストルメントの Heap Shot 機能は、これを追跡するのに役立ちます。) 私はこれを「膨張」と呼び、真のリークと区別します。どちらも無駄なメモリです。
放棄されたメモリは、メモリ リークです。ヒープショット分析は、望ましくないメモリの増加を見つけるのに役立ちます。これはそれについての良い記事です。http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/