iOSのメモリリークとその対処方法について

私たちが取り組んでいるプロジェクトの中には、おそらく、すべてが記憶とともに整然と並んでいるものはありません。 この投稿では、この種の問題に対処する方法の話に専念します。

メモリの問題には、リークやいわゆる「ゾンビ」が含まれます。 混乱したメモリが作成されるアプリケーションは不安定になり、いくつかのインターフェイス要素の消失から始まりクラッシュで終わる奇妙なものがたくさん現れます。

まず、リークとは何かを判断しましょう。 リーク-割り当てられているが、ポインタがないメモリ領域が解放されていない。 これはかなり軽薄に見え、iPhoneには大量のRAMがあり、通常のアプリケーションはせいぜい2 MBしか占有しません。 実際、すべてがそれほどバラ色ではありません。アプリケーションは最大3 MBを使用でき、メモリ警告がそれぞれ表示されるようになり、OSは「不要」と見なされる領域を解放しようとしています。 簡単に言えば、現在見えないインターフェース要素を削除します。これは見苦しいだけでなく、アプリケーションのクラッシュを引き起こす可能性もあります。 「ゾンビ」は、プログラムがアクセスしようとしているメモリの領域をすでに解放(キル)しているため、アプリケーションのクラッシュにつながります。

IOSにはガベージコレクターがあります!


多くの人(はい、私自身がこれを罪にしています)はしばしばそれが存在しないと言います。 しかし、非常に原始的ではありますが、ガベージコレクターはまだあります。 メモリ管理の原則は、オブジェクトへのリンクの数をカウントすることに基づいています。 オブジェクトにメモリを割り当てると、その数は1に設定され、0に達するとメモリが解放されます(ガベージはスローされます)。 オブジェクトを使用するたびに、リンクの数を増やす必要があり、不要になるたびに減らす必要があります。

4つの魔法の言葉があります


メモリーを管理するには、 alloccopyretainrelease 4つの単語だけを覚える必要があります。 それぞれについて個別に話しましょう。

alloc
オブジェクトにメモリを割り当て、リンクの数を1つ増やします。新しいオブジェクトを作成するたびにリンクを使用する必要があります。

copy
オブジェクト(ポインターではない)をコピーします。 コピーしているオブジェクトへの参照の数は変更せず、新しいオブジェクトへの参照の数を増やします。

retain
オブジェクトへの参照の数を増やすだけです。

release
上記の3つの操作の逆は、リンクの数を1つ減らします。

そして何か他のもの


Autorelease
これは少し異なる話です。 オブジェクトにautoreleaseメッセージを送信すると、「遅延」 releaseが発生します。 これは、何らかの理由でアクションを実行した後にオブジェクトにreleaseするメッセージを送信できない場合に必要です。 その主な用途は、メソッドによるオブジェクトの戻りです。 名前にalloccopyretainを持たないメソッドは、「承認」オブジェクトを返します。

しかし、それをどこでも使用してみませんか? これはとても便利です! 便利ですが、高価です。 オブジェクトへの参照の数がそれぞれすぐに減少しないという事実により、メモリもすぐには解放されません。 ここには落とし穴があります。3MBしかないため、一度に大量のデータを処理すると、まったく同じメモリ警告が表示されます。

Dealloc
このメソッドは、オブジェクトが削除されたときに呼び出され、オブジェクトが使用したすべての変数を解放し、最後に親でdeallocを呼び出すdeallocがあります。
- (void)dealloc {
[model release];
[view release];
[super dealloc];
}

Property
プロパティにretainassignretaincopy 3つのタイプがありcopy 。 最後の2つはすでに明確になっているはずです。 そして最初のものは、オブジェクトへの参照の数に影響を与えることなく、単に値を割り当てます。 タイプごとにセッターの正しい実装を提供します。

//assign
- (void)setList:(List *)list{
_list = list;
}

//retain
- (void)setList:(List *)list{
[_list autorelease];
_list = [list retain];
}

//copy
- (void)setList:(List *)list{
[_list autorelease];
_list = [list copy];
}

Property動作を監視する必要はなく、設定するだけで、必要に応じて値をリセットし、リセットするだけです。

デリゲート、チキン、エッグ


その過程で、大量のオブジェクトがリークしているという事実に関連する問題に遭遇しました。 相互に保持する2つのオブジェクトがあり、したがってメモリを解放しないことが判明しました。 これは、委任パターンを使用しているときに起こりました。 別のオブジェクトを作成し、それ自体をデリゲートにするオブジェクトがありました。 そして、 Delegateプロパティはretainとして登録されました。 retainassign置き換えることにより、状況が保存されます。

最後のいくつかのヒント




Ivan Ushakov、iOSチームプログラマー

Source: https://habr.com/ru/post/J117485/


All Articles