莫空面试记 1#
午後に b 站で面接を受け、メモリ管理に関する質問をされました。たくさん質問されましたが、この質問が特に印象に残りました。他の質問は分からなかったり、忘れたりしても仕方ないですが、この質問に対する答えが全くダメだったのは心が痛みます。(涙が溢れます)
帰り道に携帯の電池が切れて、このことを思い出しました。考えてみると、あれ、これが何か分かる気がする、さらに考えると、やっぱり分かる、そして当時自分が言ったことを思い出すと、静かにしたいです。
問題を見て、理解すればいい、フォーマットが間違っているとは言わない、大体こんな感じです。
@AutoreleasePool {
A = [[A alloc] init];
B = [[B alloc] init];
A.b = B;
B.a = A;
}
それから、これが循環参照を引き起こすのか、どのステップが原因なのか、説明してもらえますか?
それから私は全くダメな説明をして、面接官は見かねて、どうすれば循環参照がなくなるのかと聞いてきました。
それに対してまた全くダメな説明をしました。
今考えると、どうしてあんなことを言ったのか?驚いてしまったのかもしれません。面接官は、私が OC を学んだことがない C 言語しか知らない人だと仮定して、説明してほしいと言ったのに、私は難しい問題だと思い込んで、興奮してしまいました。。。。
ああ、涙が溢れます。もう言わないで、帰り道に考えた答えを見てみましょう。
まず、循環参照が発生しています。これは確実です。そして、どのステップかというと、最後のステップです。最後のステップがなければ、循環参照は発生しません。
- A = [[A alloc] init]
このステップで A オブジェクトが作成され、A の参照カウントは 1 になります。 - B = [[B alloc] init]
このステップで B オブジェクトが作成され、B の参照カウントは 1 になります。 - A.b = B
このステップで A オブジェクトが B オブジェクトを保持し、B の参照カウントが 1 増えます。A が B を保持しているため、B を解放するには A が先に B を解放する必要があります。 - 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;
}