4

ARCは非常に優れているように見えますが、一般的な命名規則/規則ではわかりにくい1つまたは2つのエッジケースがあります。NSThreadに関する次のカテゴリの実装を見てください。

@interface NSThread (BlockAdditions)
- (void)performBlock:(dispatch_block_t)block;
@end

@implementation NSThread (BlockAdditions)
- (void)internal_performBlock:(dispatch_block_t)block
{
    block();
}

- (void)performBlock:(dispatch_block_t)block
{
    [self performSelector:@selector(internal_performBlock:)
                 onThread:self
               withObject:[block copy]
            waitUntilDone:NO];
}

私の質問は:block電話した後に漏れ-copyますか?コンパイラは、ブロックをいつ解放するかをどのように知るのでしょうか?Instrumentsはリークを検出しませんが、ARCについて私が知っていることを考えると、このケースが正しく処理されていることを私に納得させることはできません。情報ありがとうございます!

4

2 に答える 2

5

それは保持/解放でリークしますが、ARCではリークしないはずです。

コンパイラは-copyを認識し、それはaが必要であることを意味し-releaseます。生成されたアセンブリを見ると、まさにそれが表示されているはずです。

(まあ、アセンブリを通り抜けたときに表示されるものとまったく同じですが、これは正確には単純ではありません。)

をコンパイルするだけで、アセンブリを簡略化できることに注意してください[block copy];

于 2013-01-20T22:44:50.567 に答える
1

コンパイラは、それblockがメソッドにコピーされていることを確認しperformBlock:ます。これにより、メソッドに新しいオブジェクトが作成され、メソッドが返される前に、メソッドで作成されたすべてのオブジェクトを解放する必要があります。ただし、このオブジェクトが返される場合は、自動解放する必要があります。メソッドが戻ると、コンパイラは変数を参照しないためです。メソッド内でもはや、したがってそれを解放することはできませんでした。

したがって、あなたのメソッドは大まかに次のように翻訳されます

- (void)performBlock:(dispatch_block_t)block
{
    dispatch_block_t blockCopy;

    blockCopy = [block copy];
    [self performSelector:@selector(internal_performBlock:)
                 onThread:self
               withObject:blockCopy
            waitUntilDone:NO];

    // If method returns, how shall the compiler access blockCopy any longer?
    // It can't! And since blockCopy is not returned by the method, it must
    // be destroyed before the method returns.
    [blockCopy release];
}

なぜこのコードがクラッシュしないのか、blockCopy割り当てが解除されないのではないかと思うかもしれません。いいえ、セレクターコールバックを実行するまで引数performSelector:onThread:withObject:waitUntilDone:として渡したオブジェクトを保持するため、その後、オブジェクトを再度解放します。withObject:したがってrelease、の最後にが呼び出されるとperformBlock:blockCopyretainCount2になり、このリリースでは1に減少しますが、0には減少しないため、リリースされません。セレクターが他のスレッドで呼び出された後でのみblockCopy解放され、呼び出されたセレクターがそれを保持していないため、最終的に割り当てが解除されます。

于 2013-01-21T01:34:10.587 に答える