[objective-c] ARCで@autoreleasepoolが必要なのはなぜですか?


Answers

@autoreleasepoolは何も自動@autoreleasepoolしません。 ブロックの終わりに達すると、ブロックがアクティブである間にARCによって自動リリースされたオブジェクトにリリースメッセージが送信されるように、自動解放プールが作成されます。 アップルの「 アドバンストメモリ管理プログラミングガイド」では、このように説明しています。

自動解放プールブロックの最後に、ブロック内で自動解放メッセージを受信したオブジェクトに解放メッセージが送信されます。ブロック内の自動解放メッセージが送信されるたびに解放メッセージが受信されます。

Question

ARC(Automatic Reference Counting)の大部分については、Objective-Cオブジェクトを使用してメモリ管理について考える必要はありません。 もうNSAutoreleasePoolを作成することはできませんが、新しい構文があります:

@autoreleasepool {
    …
}

私の質問は、私が手動でリリース/オートリリースする予定でないときに、なぜこれが必要なのでしょうか?

編集:私はすべてのanwersとコメントから抜け出したものを要約するために:

新しい構文:

@autoreleasepool { … }は新しい構文です

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
…
[pool drain];

さらに重要なことには:

  • ARCはautorelease releaseます。
  • これを行うには、自動リリースプールが必要です。
  • ARCは自動解放プールを作成しません。 しかしながら:
    • すべてのCocoaアプリのメインスレッドには既に自動解放プールがあります。
  • あなたが@autoreleasepoolを利用したいと思うかもしれない2つの機会があります:
    1. セカンダリスレッドで、自動解放プールがない場合、 myRunLoop(…) { @autoreleasepool { … } return success; }などのリークを防ぐために独自に作成する必要がありますmyRunLoop(…) { @autoreleasepool { … } return success; } myRunLoop(…) { @autoreleasepool { … } return success; }
    2. @mattjgallowayが答えとして示したように、より多くのローカルプールを作成したいとき。



これは、オートレリースされたオブジェクトがスコープから外れるのが安全かどうかのヒントをコンパイラに提供する必要があるからです。




この話題には多くの混乱があるようです(少なくとも80人はおそらくこれについて混乱し、コードの周りに@autoreleasepoolを振りかざす必要があると思います)。

プロジェクト(依存関係を含む)が排他的にARCを使用する場合、@autoreleasepoolは決して使用する必要はなく、何も役に立たないでしょう。 ARCは、オブジェクトを正しい時刻に解放する処理を行います。 例えば:

@interface Testing: NSObject
+ (void) test;
@end

@implementation Testing
- (void) dealloc { NSLog(@"dealloc"); }

+ (void) test
{
    while(true) NSLog(@"p = %p", [Testing new]);
}
@end

表示:

p = 0x17696f80
dealloc
p = 0x17570a90
dealloc

autoreleaseプールが終了するのを待たずに、値がスコープから外れると、各Testingオブジェクトは割り当て解除されます。 (NSNumberの例でも同じことが起こりますが、これによりdeallocを観察できます)。ARC は自動解放を使用しません。

@autoreleasepoolがまだ許可されているのは、まだ完全にARCに移行していないARCプロジェクトと非ARCプロジェクトが混在する場合です。

非ARCコードを呼び出すと、自動解放されたオブジェクトが返されることがあります。 その場合、現在の自動解放プールは決して終了しないので、上記のループはリークします。 それでコードブロックのまわりに@autoreleasepoolを置いておきたいところです。

しかし、ARCの移行を完全に完了した場合は、オートリリープールを忘れてしまいます。




Related