web-dev-qa-db-ja.com

Objective-Cの自動参照カウントは、どのようなリークを防止または最小化しませんか?

MacおよびiOSプラットフォームでは、メモリリークは多くの場合、未リリースのポインターが原因です。従来、allocs、copys、retainsをチェックして、それぞれに対応するリリースメッセージがあることを確認することが常に最も重要でした。

Xcode 4.2に付属するツールチェーンは、最新バージョンの LLVMコンパイラー で自動参照カウント(ARC)を導入します。それは非常にクールで、不必要な日常的な開発時間を大幅に削減し、適切な保持/解放バランスで簡単に修正できる不注意なメモリリークを防ぎます。 MacおよびiOSアプリでARCを有効にすると、自動リリースプールでさえも異なる方法で管理する必要があります(独自のNSAutoreleasePoolsを割り当てないようにする必要があります)。

しかし、(otherメモリリークはそれを行いますnot私がまだしなければならないことを防ぎます気をつけて?

おまけとして、Mac OS XとiOSのARCとMac OS Xのガベージコレクションの違いは何ですか?

234
BoltClock

引き続き注意する必要がある主なメモリ関連の問題は、保持サイクルです。これは、あるオブジェクトが別のオブジェクトへの強力なポインタを持っているが、ターゲットオブジェクトが元のオブジェクトへの強力なポインタを持っている場合に発生します。これらのオブジェクトへの他のすべての参照が削除された場合でも、それらは引き続き保持され、解放されません。これは、チェーンの最後のオブジェクトが以前のオブジェクトを参照している可能性があるオブジェクトのチェーンによって間接的に発生することもあります。

このため、__unsafe_unretainedおよび__weak所有権修飾子が存在します。前者はポイントするオブジェクトを保持しませんが、そのオブジェクトが消えて不良メモリを指す可能性を残しますが、後者はオブジェクトを保持せず、ターゲットが割り当て解除されると自動的にnilに設定します。 2つのうち、__weakは一般的にそれをサポートするプラットフォームで好まれます。

これらの修飾子は、オブジェクトがそのデリゲートを保持したくない場合や、サイクルを引き起こす可能性があるデリゲートなどの場合に使用します。

メモリ関連のもう1つの重要な問題は、char*などのタイプにmalloc()を使用して割り当てられたCore Foundationオブジェクトとメモリの処理です。 ARCはこれらのタイプを管理せず、Objective-Cオブジェクトのみを管理するため、引き続き自分で対処する必要があります。 Core Foundationのタイプは、特に対応が難しい場合があります。これは、一致するObjective-Cオブジェクトにブリッジする必要がある場合があり、その逆の場合もあるためです。これは、CFタイプとObjective-Cをブリッジするときに、ARCから制御をやり取りする必要があることを意味します。このブリッジングに関連するいくつかのキーワードが追加されました。MikeAshは 彼の長いARCの記述 でさまざまなブリッジングの事例を説明しています。

これに加えて、頻度は少ないが潜在的に問題のある他のいくつかのケースがあり、 公開された仕様 が詳細に説明されています。

オブジェクトへの強力なポインタがある限りオブジェクトを保持することに基づいた新しい動作の多くは、Macのガベージコレクションに非常に似ています。ただし、技術的基盤は大きく異なります。指摘されていないオブジェクトをクリーンアップするためにガベージコレクタープロセスを定期的に実行するのではなく、このスタイルのメモリ管理は、Objective-Cで従う必要がある厳格な保持/解放ルールに依存しています。

ARCは、長年行っていた繰り返しのメモリ管理タスクを単純に受け取り、それらをコンパイラにオフロードするので、再び心配する必要はありません。このように、ガベージコレクションプラットフォームで発生する停止問題やノコギリメモリプロファイルはありません。ガベージコレクションされたMacアプリケーションでこれらの両方を経験しましたが、ARCでの動作を確認したいと思っています。

ガベージコレクションとARCの詳細については、 Objective-CメーリングリストのChris Lattnerによるこの非常に興味深い応答 を参照してください。ここでは、Objective-C 2.0ガベージコレクションに対するARCの多くの利点を示しています。彼が説明するいくつかのGCの問題に遭遇しました。

261
Brad Larson

ARCは、ObjC以外のメモリをサポートしません。たとえば、malloc()何かをした場合でも、free()する必要があります。

コンパイラがセレクタが何であるかを理解できない場合、ARCはperformSelector:にだまされる可能性があります(コンパイラはそのことについて警告を生成します)。

また、ARCはObjC命名規則に従ってコードを生成します。そのため、ARCとMRCコードを混在させた場合、MRCコードがコンパイラが名前の約束どおりに動作しない場合、驚くべき結果を得ることができます。

14
Stripes

次の4つの問題により、アプリケーションでメモリリークが発生しました。

  1. View Controllerを閉じるときにNSTimersを無効にしない
  2. View Controllerを閉じるときに、オブザーバーをNSNotificationCenterから削除するのを忘れます。
  3. ブロックへの自己への強い参照を保持します。
  4. View Controllerプロパティでデリゲートへの強参照を使用する

幸いなことに、私は次のブログ投稿に出会い、それらを修正することができました: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/

7
Ed-E G

Xcode 9は、このような問題を見つけるための優れたツールを提供します。 「デバッグメモリグラフ」と呼ばれます。それを使用すると、クラスタイプごとにリークしたオブジェクトを見つけることができ、そこからリリースすることで問題を解決することで、誰がそのオブジェクトへの強い参照を保持しているかを明確に確認できます。また、メモリサイクルを検出します。

使用方法の詳細を参照

0

ARCはCoreFoundationタイプも管理しません。それらを「ブリッジ」できます(CFBridgingRelease()を使用)。ただし、Objective-C/Cocoaオブジェクトとして使用する場合のみです。 CFBridgingReleaseは、CoreFoundationの保持カウントを1減らすだけで、Objective-CのARCに移動することに注意してください。

0
MaddTheSane