1

GCが有効になっているObjectiveCプロジェクトでは、次のようにスタックに可変サイズの配列を割り当てています。

MaValue *myStack = alloca((sizeof(id) * someLength));

(これを実行する理由は重要ではありません:)次に、ループ内で、myStackにデータをプッシュおよびポップします。私がスタックにプッシュするもののいくつかは、他のどこからも参照されていない新しいオブジェクトです。

私の直感は、Objective Cのガベージコレクターがそれらのポインターについて知らないため、新しい(そうでなければ参照されていない)オブジェクトを収集することを示しています。その信念の一部は、Objective C GCは実際には保守的ではなく、「そのポインタを知っている」(たとえば、スタックマップを通じて)という考えに由来しています。

ただし、すべての実験([[NSGarbageCollector defaultCollector] collectExhaustively]呼び出しを挿入)では、これらのオブジェクトを収集できませんでした。これは良いことですが、予期しないことです。したがって、GCはスタック全体をスキャンしているようであり、たとえば、有効なポインターの値を持つ整数が実際にはポインターであると控えめに想定しています。

あれは正しいですか?それとも私は何かが足りないのですか?

4

1 に答える 1

3

正しく動作しています。

コレクターは、各クラスにレイアウトがあり、オブジェクトを参照するか__strongを使用するスロットのみがスキャンされるという点で、ヒープを正確に[可能な限り]スキャンしますが、スタックは控えめにスキャンする必要があります。スタック上のすべてのポインターサイズおよびポインター整列スロットは、参照のためにスキャンする必要があります。

したがって、alloca()はスタックポインタを下げ、コレクターはそのすべてをスキャンします。動作が未定義であるため、割り当てられたスペースがポインタに揃えられていることを確認するために、おそらくアサーションをスローする必要があります。

実際には、alloca()をまったく使用しないでください。マニュアルページでさえ

alloca()関数は、マシンとコンパイラに依存します。その使用はお勧めしません。

代わりに、を使用NSAllocateCollectable()して、スキャンされたヒープスペースのチャンクを割り当てます。他の操作と比較して多くの割り当てについて話しているのでない限り、オーバーヘッドは最小限に抑える必要があります。さらに、スレッドの最大スタックサイズ(大きくはなく、実行しているスレッドとその割り当て方法によって異なります)を超えるリスクが[ほぼ同じくらい]実行されなくなります。

于 2009-12-04T16:41:56.407 に答える