8

Objective-CコマンドラインおよびiOSプログラム用の Xcode 4.x テンプレートが@autoreleasepool {}パーツ ラッピングmain()のコードを追加するのはなぜですか? これは、 OS Xアプリケーション テンプレートでは発生しないことに注意してください。

OS X アプリケーションが同じことをしないのはなぜですか? 両方が同じ方法を使用しないのはなぜですか?

最後に、プログラムが終了するとすべてのメモリが解放されるのに、なぜこれらすべてが実際に重要なのでしょうか?


あるいは別の言い方をすれば、コマンド ラインiOSのObjective-C プログラム@autoreleasepool { ... }で inを省略すると、実際にはどのような結果になるのでしょうか?main()

これら 2 つのコードはコンパイルされ、同等に動作するように見えます。

1.

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSArray *array = @[@"Hello, world!"];
        NSLog(@"%@", array[0]);
    }
    return 0;
}

2.

int main(int argc, const char * argv[])
{
    NSArray *array = @[@"Hello, world!"];
    NSLog(@"%@", array[0]);
}

注意してください、私は ARC コンテキストでの説明のみを気にします。ARC は、 の明示的な使用を禁止していますautorelease

4

4 に答える 4

5

autoreleaseスタックに自動解放プールがない場合は機能しません。

object-c で自動解放されたオブジェクトを使用する必要は実際にはありません (例で行っているように)。したがって、理論的には省略できますが、ほとんどの Apple フレームワークは自動解放されたオブジェクトを頻繁に使用します。

通常、すべてのスレッドには少なくとも 1 つの自動解放プールが必要です。そうしないと、Obj-C コードを使用するのは非常に安全ではありません。その場合、最初に自動解放プールを設定することmainは非常に良い方法です。

編集:

ARC では、明示的な呼び出しautoreleaseは禁止されていますが、autorelease呼び出しはまだ存在します (コンパイラによって追加されます)。これは、自動解放プールが必要であることを意味します。

これは、メモリの解放とは関係ありません。自動解放プールの存在そのものが必要です。たとえそれが決して排水されていなくても。

プログラマーはガベージコレクターも使用できるため、OS X はテンプレートに自動解放プールを追加しないと思います (ただし、現在は廃止されています)。

編集2:

OS X プロジェクトを作成したところ、@autoreleasepoolそこにあります。実際、それがない唯一のテンプレートは、実際には Obj-C ではなく、純粋な C である「Core Foundation」プロジェクトです。

EDIT 3:(もう少し考えてグーグルで調べた後)

ARC の導入により、自動解放プールが書き直されました。以前はフレームワーク機能でしたが、現在は言語 (Obj-C) 機能です。それらは異なる方法で実装されます。現在、すべての新しいスレッドには暗黙的な自動解放プールがあるようです。を使用@autoreleasepoolすると、スレッド スタックに新しい自動解放プールが実際に作成されるわけではなく、暗黙的な自動解放プールにマークが付けられるだけです (マークの後に自動解放されたすべてのものを排出できるようにするため)。つまり、@autoreleasepoolが省略されたときに警告またはエラーをトリガーする例を作成する方法はありません。

ただし、これは実装の詳細と見なされるため、将来 (または別のコンパイラが使用される場合) に簡単に変更できます。@autoreleasepoolそのため、新しいスレッドごとに for を設定することをお勧めします (-[NSThread detachWithSelector:..]ドキュメントなどで言及されています)。

于 2013-08-24T19:54:15.433 に答える
3

上記のコード例では、自動解放されたオブジェクトをまったく使用していません。

しかし、あなたがこのようなことをしていたとしたら:

NSString * somethingToSay = [NSString stringWithString:@"this is an autoreleased string, believe it or not"];
NSLog(@"%@", somethingToSay);
return 0;

" @autoreleasepool" ビットは、実際にはもう少し便利です。

autoreleasepool に関する Apple のドキュメントを見ると、彼らは次のように述べています。

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

そのため、自動解放されたオブジェクトが多数ある場合 (そして、最終的に NSArray、NSDictionary、NSString などになるように作成できるものがたくさんある場合)、これらの自動解放プールはメモリを解放し続けるのに役立ちます。

アプリケーション テンプレートの@autoreleasepoolmain.m にUIApplicationMain「ほとんどの人は、再起動するまで iPhone アプリを実行したままにしますが、再起動する可能性があります)。

于 2013-08-24T19:28:36.960 に答える
2

ドキュメントに必要と書かれているので必要です。これで十分です。ドキュメントを信頼してください。

通常、独自の自動解放プール ブロックを作成する必要はありませんが、作成する必要がある、または作成することが有益な場合があります。

...

Cocoa は、コードが自動解放プール ブロック内で実行されることを常に想定しています。そうしないと、自動解放されたオブジェクトが解放されず、アプリケーションでメモリ リークが発生します。(自動解放プール ブロックの外に自動解放メッセージを送信すると、Cocoa は適切なエラー メッセージをログに記録します。)

... ただし、独自の自動解放プール ブロックを使用する場合が 3 つあります。

  • コマンドライン ツールなど、UI フレームワークに基づかないプログラムを作成している場合。
  • ...
  • ...

...

Foundation 専用のプログラムを作成している場合、またはスレッドを分離している場合は、独自の自動解放プール ブロックを作成する必要があります。

自動解放プールがない場合...ほとんどのものは問題なく動作しますが、それは「すべて」ではなく「ほとんど」のものです。彼らは 2 つの理由しか述べていませんが、文書化されていない他の理由がある可能性があり、この動作はすべて将来いつでも変更される可能性があります。

推奨されるベスト プラクティスに従えば、コードは 20 年後も完全に機能するはずですが、そうしないと、オペレーティング システムの次の xxx アップデート以降、50 回の実行ごとにランダムにクラッシュする可能性があります。

于 2013-08-25T12:14:18.070 に答える
1

おそらく、Appleのドキュメントからのこの引用が役立つでしょう:

切り離されたスレッドが Cocoa 呼び出しを行わない場合、自動解放プール ブロックを使用する必要はありません。

マスタースレッド(「メイン」がある場合)でも、すべてのスレッドに推定できます。

于 2014-07-20T12:04:51.147 に答える