237

Mac および iOS プラットフォームでは、解放されていないポインターが原因でメモリ リークが発生することがよくあります。伝統的に、allocs、copys、retains をチェックして、それぞれに対応するリリース メッセージがあることを確認することが常に最も重要でした。

Xcode 4.2 に付属するツールチェーンは、最新バージョンのLLVM コンパイラで自動参照カウント (ARC) を導入します。これは、コンパイラにメモリ管理を任せることで、この問題を完全に解消します。これは非常に優れており、不必要でありふれた開発時間を大幅に削減し、適切な保持/解放のバランスで簡単に修正できる多くの不注意なメモリ リークを防ぎます。Mac および iOS アプリで ARC を有効にする場合は、自動解放プールでさえ別の方法で管理する必要があります (独自NSAutoreleasePoolの を割り当てるべきではないため)。

しかし、まだ気をつけなければならないことを防げない、にどのようなメモリリークがありますか?

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

4

5 に答える 5

263

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

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

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

メモリ関連のもう 1 つの重要な問題は、Core Foundation オブジェクトの処理と、 などmalloc()の型を使用して割り当てられたメモリchar*です。ARC はこれらの型を管理せず、Objective-C オブジェクトのみを管理するため、自分で処理する必要があります。Core Foundation 型は、対応する Objective-C オブジェクトにブリッジする必要がある場合があり、その逆も同様であるため、特に注意が必要です。これは、CF 型と Objective-C の間を橋渡しするときに、制御を ARC から前後に転送する必要があることを意味します。このブリッジングに関連するいくつかのキーワードが追加されました。Mike Ash は、彼の長い ARC の記事で、さまざまなブリッジングのケースについて優れた説明をしています。

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

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

ARC は、何年にもわたって行わなければならなかった繰り返しのメモリ管理タスクをコンパイラにオフロードするだけなので、二度と心配する必要はありません。このようにすると、ガベージ コレクション プラットフォームで発生する停止の問題やノコギリのメモリ プロファイルは発生しません。私はガベージ コレクションを行った Mac アプリケーションでこれらの両方を経験しており、ARC の下でそれらがどのように動作するかを知りたいと思っています。

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

于 2011-06-17T16:11:08.727 に答える
14

ARC は ObjC 以外のメモリでは役に立ちませmalloc()free()

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

ARC はまた、ObjC の命名規則に従ってコードを生成するため、ARC と MRC コードを混在させると、名前が約束しているとコンパイラが考えていることを MRC コードが実行しない場合に、驚くべき結果が得られる可能性があります。

于 2011-11-22T08:24:45.980 に答える
7

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

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

幸いなことに、次のブログ投稿を見つけて修正することができました

于 2015-06-06T23:40:01.920 に答える
0

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

于 2013-01-17T21:57:37.810 に答える
0

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

詳しい使い方を見る

于 2018-04-12T14:40:53.910 に答える