Objective-C 2.0 及びARCにおけるメモリ管理の妄想

たぶんこんな感じなのかなーと妄想。
後でライブラリの実装みてみよう。

ガベージコレクションが未実装のC言語の場合
malloc/dealloc、new delete で直接解放
カプセル化されたSDKの場合一般的に Object->Release() で解放
・オブジェクトの参照はメモリアドレスのコピーを行うだけ

この場合、解放=メモリ上からの削除なのでオブジェクトのポインタを多岐にわたって参照していた場合にAccess Violationが発生する可能性が高くなる。(しかもアドレスだけしか表示されなかったり、強制終了がメインなのでデバッグが大変。)

寮内でのゲームの貸し出しに例えると、
・Aさんがゲームを買ってきて「ぼうけんのしょ」を作る。
・BさんがAさんと仲が良いので「ぼうけんのしょ」を作る。
・CさんはBさんと仲が良いので「ぼうけんのしょ」を作る。
・AさんはBさんがクリアしたのを確認してゲームを売りに行く。
・Cさんがゲームをプレイしようと思ったらゲームがもう無い!(Access Violation)

という感じですね。

さてここからは実装を見ていない妄想です。

iPhoneにおけるObjective-C 2.0の場合
・Pointerでオブジェクトを生成する際に必ず管理プールに登録してカウントを+1する
・オブジェクトの参照時に必ず管理プールに登録されたカウントを+1する
・オブジェクトの参照をやめる際にreleaseを呼ぶと管理プールに登録されたカウントを-1する
 ※C言語と違ってreleaseを呼んだ瞬間に解放することはない
GUI向け開発言語なので最初からメインループがあり、メインループの終了時にカウントが0になっているオブジェクトをメモリ上から解放する

恐らくこんな感じだと思うのですが、Objective-Cでプログラミングをしている限り、Pointerが曖昧になり、管理プールの存在にいたってはカプセル化により完全に隠蔽されているため実際の挙動がつかめない状況です。(importファイルのライブラリと実装状況を漁るしかない。)
このような実装にした理由としては、Objective-Cの名前にもある通りオブジェクト指向につくられた言語なので参照が多岐にわたる機会が非常に多いなかでAccess Violationを防ぐためでしょうか、最悪カウントが0にされないまま残っても動作は保証されます(メモリリーク)。またretainを忘れるとクラッシュする可能性が残っています。

寮内でのゲームの貸し出しに例えると、
・Aさんがゲームを買ってきて「ぼうけんのしょ」を作る。
 ケースの中に「プレイ中」の付箋紙をいれておく。
・BさんがAさんと仲が良いので「ぼうけんのしょ」を作る。
 ケースの中に「プレイ中」の付箋紙をいれておく。(現在2枚)
・CさんはBさんと仲が良いので「ぼうけんのしょ」を作る。
 ケースの中に「プレイ中」の付箋紙をいれておく。(現在3枚)
・Bさんがゲームをクリアする。
 ケースの中から「プレイ中」の付箋紙を取り出す。(現在2枚)
・Aさんがゲームを売りに行こうとするが、
 「プレイ中」の付箋紙が2枚、Aさんの分ともうひとり誰かプレイ中の人の分があるのでやめる。
・Cさんがゲームをクリアする。
 ケースの中から「プレイ中」の付箋紙を取り出す。(現在1枚)
・Aさんがゲームを売りに行く。
 ケースの中に「プレイ中」の付箋紙が1枚しかない状態なので問題ない。

実際の解放者はAさんではないので妄想実装との違いがありちょっと苦しいですが、こんな感じですね。

ARCの場合
・Pointerでオブジェクトを生成する際に必ず管理プールに登録してカウントを+1する
・オブジェクトの参照時にコンパイラがスコープを把握した上で管理プールのカウントを+1する
・オブジェクトがスコープ外に出た際に管理プールのカウントを-1する
・生成後のカウント部分をコーディングしようとするとエラーになる
・ルールを使いたくない時はstrongやweakなどの特別な修飾子を使う

これにより可視コードを減らすとともにObjective-C 2.0の場合に記載した赤字部分がほぼ解消されます。
ルールが増えた分、特殊な場合の制約が生じてしまいます。
また、初心者にとっての敷居が低くなりますが、その分メモリ管理の把握が非常に難しいという弊害があると思います。
トータルとしては一長一短というところでしょうか。

冗長になってしまいますのでたとえを省略しますが、妖精さんがクリア状況を常に把握して付箋紙を入れてくれる感じですね。