2

私は、ARCと、適切なライフタイム修飾子(、、、、および)を選択するための適切なユースケースについてかなりよく理解している__strongと思い__weakます。しかし、私のテストでは、私には意味をなさない1つの例を見つけました。__unsafe_unretained__autoreleasing

私が理解しているように、両方とも保持カウントを追加__weak__unsafe_unretainedません。したがって、オブジェクトへの他のポインタがない場合__strong、オブジェクトは即座に割り当て解除されます(不変の文字列はこのルールの例外です)。このプロセスの唯一の違いは、__weakポインターがnilに設定され、__unsafe_unretainedポインターがそのまま残されることです。

__weak単純なカスタムオブジェクト(1つのNSStringプロパティで構成される)へのポインターを作成すると、プロパティにアクセスしようとしたときに期待される(null)値が表示されます。

Test * __weak myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: (null)

__unsafe_unretained同様に、結果として生じるダングリングポインターが原因で、ライフタイム修飾子がクラッシュを引き起こすと予想します。ただし、そうではありません。この次のテストでは、実際の値を確認します。

Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: Hi!

__unsafe_unretainedオブジェクトの割り当てが解除されないのはなぜですか?

[編集]:オブジェクトの割り当てが解除されています... 2〜3行目をNSLog(@"%@", myTest);アプリのクラッシュに置き換えようとすると(最初の行の直後にオーバーライドされたが呼び出されます)deallocTest不変の文字列は、を使用しても引き続き使用可能であり__unsafe_unretained、NSStringへの直接ポインタが機能することを私は知っています。割り当て解除されたオブジェクトにプロパティを設定でき(2行目)、後で割り当て解除されたオブジェクトへのポインターからプロパティを逆参照できることに驚いています(3行目)。誰かがそれを説明できれば、それは間違いなく私の質問に答えるでしょう。

4

5 に答える 5

2

objcの定数文字列はヒープアドレスへの定数ポインタであり、アドレスはまだ有効であるためです。

コメント後に編集:

テストオブジェクトアドレスのメモリが上書きされておらず、まだそのオブジェクトが含まれているためでしょうか。憶測....

于 2012-11-20T16:57:36.467 に答える
2

割り当て解除されたオブジェクトにプロパティを設定でき(2行目)、後で割り当て解除されたオブジェクトへのポインターからプロパティを逆参照できることに驚いています(3行目)。誰かがそれを説明できれば、それは間違いなく私の質問に答えるでしょう。

オブジェクトの割り当てが解除されると、ゼロ化されません。割り当て解除されたオブジェクトへのポインタがあり、プロパティ値はそのポインタへのオフセットで格納されるため、そのプロパティ値の格納と取得は割り当て解除後に成功する可能性があります。また、何らかの理由ですべてが爆発する可能性もあります。他の。

コードが機能することは非常に壊れやすいので、「デバッグ中に逆アセンブリを表示」でデバッグしてみてください。ステップスルーすると、アクセス違反が発生するか、Xcode自体が停止する可能性があります...

C、Objective-C、C ++、またはそのファミリのいずれかで奇妙なことが起こることに驚かないでください。代わりに、いくつかの奇妙なことが起こっていることにあなたの驚きを予約してください!

于 2012-11-21T00:21:44.547 に答える
1

Testそのメソッドを実装し、-deallocいくつかの単純なロギングを追加することで、いつ割り当てが解除されるかを確認できます。

ただし、Testの割り当てがすぐに解除された場合でも、RAMで占有していたメモリは、呼び出した時点で変更されないままになる可能性がありますmyVal

于 2012-11-20T17:11:54.147 に答える
1

@"hi!"事実上、シングルトンである静的グローバル定数文字列インスタンスを生成します。したがって、そもそも実際には割り当てられていないため、割り当てが解除されることはありません(少なくとも、通常のヒープ割り当てではありません)。

オブジェクトの寿命の問題を調査する場合は、常にNSObjectのサブクラスを使用して、動作を保証し、動作をオーバーライドしてロギングフックを簡単にドロップできるようにします。

于 2012-11-20T17:23:22.257 に答える
0

そこには何も奇妙なことはありません…オブジェクトを存続させるには、オブジェクトへの強い参照が少なくとも1つ必要です。

Test * anTest = [[Test alloc] init];
Test * __weak myTest = anTest;
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: (Hi)
于 2013-05-28T13:39:50.187 に答える