0
MyBlock getBlocks()
{    
    MyBlock myBlock = ^{
        NSLog(@"Hello World!");
    };

    return myBlock;
}

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    MyBlock myBlock = getBlocks();

    myBlock();

    [pool drain];

    return 0;
}

このコード スニペットが機能するのはなぜですか? myBlock を破棄する必要があります。

ちなみに、このスニペットも機能します。

NSObject *obj = [[NSObject alloc] init];

NSLog(@"%ld", [obj retainCount]);

MyBlock myBlock = ^{
    NSLog(@"Hello World!");
    NSLog(@"%ld", [obj retainCount]);
};

[obj release];

しかし、ブロック内の [obj preserveCount] は 2 ではなく 1 を出力します。なぜですか?

4

2 に答える 2

3

このコード スニペットが機能するのはなぜですか?

ブロックの実装には周囲のスコープへの参照がなく、clang によってグローバルブロックとして構成されているため、最初の切り取りが機能しています。これにより、ブロックは通常のようにスタックに置かれなくなります。

myBlock を破棄する必要があります。

スタック フレーム (およびそのローカル変数) は破棄されません。それらのメモリは、さらに割り当てることができるようになります。とにかく、あなたの例が単純であるため、スタックフレームに存在しないグローバルブロックを取得しています。

周囲のスコープへの参照を行っていた場合、スタックベースのブロックmyBlockがあり、所有されているメモリの場所へのダングリング ポインターになり、クラッシュにつながる可能性があります。

[obj retainCount]ブロックプリントでは 2 ではなく 1 ですが、なぜですか?

合理的に聞こえます。

オブジェクトを割り当てています (保持カウント: 1)、ブロックはそれを保持しています (保持カウント: 2)、それを解放しています (保持カウント: 1)、ブロックは最終的に実行されます (保持カウントはまだ 1)。

とにかく、一般的な注意として、retainCountメモリについて推論するときは頼りにしないでください。retainCountメモリ管理プロセスは内部で多くのことが行われており、実装の内部の詳細を考慮することはできないため、 の値を見るだけでは何も言えません。詳細はこちら: http://whentouseretaincount.com/

于 2013-08-20T10:05:53.980 に答える