0

この SO の質問に対する Bavarous の回答に基づいて@autoreleasepool、LLVM/clang でビルドする場合、これは Objective-C 言語の機能であると信じるようになりました。

この場合、非 ARC 環境での@autoreleasepool代わりにを使用するように次のコードをどのように書き直しますか?NSAutoreleasePool

[NSAutoreleasePool addObject:anObject]; // (*)

背景: 私は基本的に、クラスと相互作用-autoreleaseないカスタム実装を書きたいと思っています:NSAutoreleasePool

@autoreleasepool {
    SomeCls *obj = [[SomeCls alloc] init];
    [obj autorelease]; // Does not go through an NSAutoreleasePool object
    // ...
}
4

5 に答える 5

3

@autoreleasepool { }は、関数の終了ポイントごとに現在のプールを空にする必要をなくすための新しい言語機能です。今、書く代わりに:

void f(void) {
    //Make a new pool
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    //Every inner scope that exits prematurely requires a drain
    if (life_is_good) {
        for (int i = 0; i < 1000; i++) {
            NSObject *obj = [[[NSObject alloc]init]autorelease];
            //breaks out of the loop, and the function, so drain the pool
            if (life_is_bad) {
                [pool drain];
                return;
            }
        }
        //Life gets bad below here, so return
        [pool drain];
        return;
    }
    //end of function requires drain.
    [pool drain];
}

関数全体を@autoreleasepool { }ディレクティブでラップすると、コンパイラは関数が返す場所に適切なドレインを挿入します。

void f(void) {
    //Make a new pool
    @autoreleasepool {
        if (life_is_good) {
            for (int i = 0; i < 1000; i++) {
                NSObject *obj = [[[NSObject alloc]init]autorelease];
                //breaks out of the loop, and the function, so drain the pool
                if (life_is_bad) {
                    //[pool drain]; auto-drain
                    return;
                }
            }
            //[pool drain]; auto-drain
            return;
        }
        //[pool drain]; auto-drain
    }
}

自動プール メカニズムは膨大な量の作業 (ページ管理、スレッドごとのプール管理、タイムリーかつ効率的な方法でのオブジェクトの解放) を処理するため、なぜ自動プール メカニズムを放棄したいのかわかりませんが、そうすべきではありません。プリミティブな NSAutoreleasePool を起動して実行するのは面倒です。autoreleasepool には、ページ マネージャー (malloc()およびrealloc())、ポインター ストレージ (単純な配列)、およびそれが使用されている現在のスコープが終了したかどうかを検出する何らかの方法 ( -drain) が必要です。単純なプールはスレッドセーフなシングルトンにすぎませんが、その実装で一度に挿入および削除しようとするオブジェクトの数に注意してください。あまりにも多くのオブジェクトにあまりにも多くのホット ページを割り当てようとすると、segfault が発生する可能性があります。

于 2013-07-07T13:54:39.350 に答える
1

この SO の質問に対する Bavarous の回答に基づいて、LLVM/clang でビルドする場合、@autoreleasepool は現在、Objective-C 言語の機能であると信じるに至りました。

正しい。

この場合、非 ARC 環境で NSAutoreleasePool の代わりに @autoreleasepool を使用するように次のコードをどのように書き直しますか?

[NSAutoreleasePool addObject:anObject]; // (*)

Doc: 通常、このメソッドを直接呼び出すことはありません。代わりに autorelease を object に送信します。

@autoreleasepool {
 id anObject = ...;
 [anObject autorelease];
}

背景: 私は基本的に、NSAutoreleasePool クラスとはまったく対話しない -autorelease のカスタム実装を書きたいと思っています。

もはやサブクラス化することさえできませNSAutoreleasePoolん (意味のある方法で)。自由に自動解放できる他の A​​PI にオブジェクトを渡さない限り、オブジェクトは現在の自動解放プールに格納されてしまいます。今日のこのメカニズムは、オブジェクトベースでさえありません。

これが不可能な場合は、NSAutoreleasePool を使用しない回避策の提案を受け付けます。

どのような問題を解決しようとしているのかは定かではありませんが、以下を使用して寿命を延ばすことができます:

NSMutableArray * fauxAutoreleasePool = NSMutableArray.new;
id anObject = ...;
[fauxAutoreleasePool addObject:anObject];
...
[fauxAutoreleasePool removeAllObjects]; // << explicitly drain, which also happens when the array is destroyed

もちろん、独自の実装を作成することもできます。なぜ独自のコードを作成するのかはまだ謎であり、製品コード (@autoreleasepoolうまく動作) には適していません。

于 2013-07-08T10:16:51.493 に答える
0

背景: 私は基本的に、NSAutoreleasePool クラスとはまったく対話しない -autorelease のカスタム実装を書きたいと思っています。

-autoreleaseと相互作用するものは何だと思いますNSAutoreleasePoolか?

iOS 5 以降または Mac OS X 10.7 以降で実行している限り、@autoreleasepoolとの両方-[NSObject autorelease]がランタイム自動解放プール管理関数を使用し、まったく関係ありませんNSAutoreleasePool(NSAutoreleasePoolこれらの OS バージョンでは、ランタイムの単なるラッパーです)。機能)。

于 2013-07-07T18:22:07.993 に答える
0

ブロックの最後に@autoreleasepool、自動解放されたオブジェクトにreleaseメッセージが送信されます。

メソッドを再実装する場合、サブクラスにメッセージをautorelease直接送信したくない場合があります。もしそうなら、いくつかの特別な振る舞いで再実装することはあなたの仕事をすることができます.releaseNSObjectrelease

于 2013-07-06T10:27:25.243 に答える