Objective-C は (主に) 参照カウント メモリ モデルを使用します。手動参照カウントと自動参照カウント (ARC) があります。
ARC の仕組み
手動で参照カウントを行ったことがあり、clang 静的アナライザー ツールを実行したことがある場合は、それがメモリ リークを見つけるという驚くべき仕事をしていることに気付くでしょう。これが ARC の背後にある考え方です。アナライザーがリークを見つけるのにこれほど優れているのであれば、なぜメモリ管理を実行させないのでしょうか?
したがって、分析はコンパイル時に行われ、結果のコードには保持呼び出しと解放呼び出しが組み込まれます。これが ARC の基盤であり、優れたメモリ モデルであり、パフォーマンスと使いやすさのバランスが取れています。ガベージ コレクションとは異なり、追加の CPU サイクルやバッテリの消耗を必要としないため、モバイル コンピューティングで特に役立ちます。
(注: ARC は弱い参照も導入します。これは、実行時にダングリング ポインターを無効にする方法です)。
ARC の使用は、ガベージ コレクションほど単純ではありません。参照カウント メモリ モデルがどのように機能するかを知る必要があります。次の問題が発生する可能性があります。
保持サイクル
メモリ リークの主な原因は保持サイクルです。これは、オブジェクト A がオブジェクト B への参照を持ち、オブジェクト B がオブジェクト A を参照する場所です。たとえば、AirlineFlight には Passenger が含まれ、Passenger には AirlineFlight -> メモリ リークがあります。
これは、ココアでは非常に一般的です。もう 1 つの例は、ViewController がビューを所有し、View には ViewController であるデリゲートがあります。おなじみですか?
保持サイクルを回避するには、オブジェクトの 1 つが他のオブジェクトを保持しないようにする必要があります。最も一般的な方法は、1 つを親として指定し、もう 1 つを子として指定することです。親は子を保持しますが、子は親を保持しません。例:
ビューコントローラー
@interface MyViewController
@property (nonatomic, strong) MyView* view
@end
意見
@interface MyView
@property (nonatomic, assign) MyViewController* controller
@end
リテイン サイクルが中断され、メモリ リークが発生しなくなりました。
ぶら下がりポインタ
上記の例ではメモリ リークはなくなりましたが、ダングリング ポインターという別の問題が発生する可能性があります。ビューにはコントローラーへの参照がまだ残っていますが、ビューコントローラーはなくなる可能性があります。コントローラーを呼び出すと、クラッシュが発生するようになりました。
これを修正するには、次の 2 つの方法があります。
dealloc メソッドでコントローラーへの参照を nil アウトします。. . しかし、おそらくただ
次のように弱参照を使用します。
@property (nonatomic, weak) MyViewController* controller
iOS 5 以降 (または OSX 10.7) には、ダングリング ポインターを追跡し、それらを無効にする小さなランタイム ユーティリティがあります。これらは弱参照と呼ばれます。
メモリ リークの検出
いくつかの方法があります。
- 保持サイクルを検出するには、clang 静的アナライザーを使用します。
- 楽器ツールを使用する
- コントローラーやその他の重要なクラスの dealloc メソッドにログ ステートメントを入れて、それらが確実に解放されるようにするのが好きです。
ダングリング ポインターの検索
- 環境変数 NS_ZOMBIES_ENABLED でコンパイルします (または、Xcode でスキームを編集し、チェックボックスをクリックして、このパラメーターを設定します)。
自動解放プール
発生する可能性のある別の問題は、実行ループ内で割り当てられるオブジェクトが多すぎることです。. これを修正するには、メイン プール内に別の自動リリース プールを作成します。
@autoreleasepool
{
}
(あなたの場合、これは問題ではないと思います)。