今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

莫空面接記1

莫空面试记 1#

午後に b 站で面接を受け、メモリ管理に関する質問をされました。たくさん質問されましたが、この質問が特に印象に残りました。他の質問は分からなかったり、忘れたりしても仕方ないですが、この質問に対する答えが全くダメだったのは心が痛みます。(涙が溢れます)

帰り道に携帯の電池が切れて、このことを思い出しました。考えてみると、あれ、これが何か分かる気がする、さらに考えると、やっぱり分かる、そして当時自分が言ったことを思い出すと、静かにしたいです。
image1

問題を見て、理解すればいい、フォーマットが間違っているとは言わない、大体こんな感じです。

@AutoreleasePool {
  A = [[A alloc] init];
  B = [[B alloc] init];
  A.b = B;
  B.a = A;
}

それから、これが循環参照を引き起こすのか、どのステップが原因なのか、説明してもらえますか?

それから私は全くダメな説明をして、面接官は見かねて、どうすれば循環参照がなくなるのかと聞いてきました。

それに対してまた全くダメな説明をしました。

今考えると、どうしてあんなことを言ったのか?驚いてしまったのかもしれません。面接官は、私が OC を学んだことがない C 言語しか知らない人だと仮定して、説明してほしいと言ったのに、私は難しい問題だと思い込んで、興奮してしまいました。。。。

ああ、涙が溢れます。もう言わないで、帰り道に考えた答えを見てみましょう。

まず、循環参照が発生しています。これは確実です。そして、どのステップかというと、最後のステップです。最後のステップがなければ、循環参照は発生しません。

  1. A = [[A alloc] init]
    このステップで A オブジェクトが作成され、A の参照カウントは 1 になります。
  2. B = [[B alloc] init]
    このステップで B オブジェクトが作成され、B の参照カウントは 1 になります。
  3. A.b = B
    このステップで A オブジェクトが B オブジェクトを保持し、B の参照カウントが 1 増えます。A が B を保持しているため、B を解放するには A が先に B を解放する必要があります。
  4. B.a = A
    このステップで B オブジェクトが A オブジェクトを保持し、A の参照カウントが 1 増えます。同様に B が A を保持しているため、A を解放するには B が先に A を解放する必要があります。

これで循環参照が発生しました。

最後に、どうすれば彼らを正常に解放できるか?もっと簡単です。最後のステップが循環参照を引き起こしているので、最後のステップを変更します。B が A を保持しているため循環参照が発生するので、B が A を保持しないようにします。__weak を使います。。。弱い参照で、参照カウントは増えません。

@AutoreleasePool {
  A = [[A alloc] init];
  B = [[B alloc] init];
  A.b = B;
  __weak weakB = B;
  weakB.a = A;
}
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。