Objective-C の季節 - retain

皆さん GC のない Objective-C でガシガシメモリ管理してますか?ボクはしてますよ〜♪まあ近頃は Objective-C == iPhone アプリみたいな感じですから、している皆さんも多いのではないでしょうか。

さて retain です。Cocoa フレームワークの NSObject クラスのインスタンスは、 それぞれが参照カウンタを保持していて、これを増やしたり減らしたりして、値がまだ所有されているかどうかを判断し、所有者がいなくなった段階で、必要なくなったぞということで、値の破棄を行うわけですが…

そんなことは、破棄する必要のあるインスタンスの都合であって、必要の無いインスタンスには関係のないことです。とはいえそんなインスタンス、あるんでしょうか?
実はあって、例えばシングルトンなクラスのインスタンスは、破棄されてしまうと困る、ですから通常、破棄されることはありません。分かり易いところだと、Cocoa フレームワークの NSNull なんかがそうです。

というわけで、そういったクラスの retain や release, retainCount は、通常とは違う実装、つまり、retain や release は何もしない、retainCount は適当な値(UINT_MAX や -1)を返す、そういう風になっているべきで、シングルトンなクラスを自分で記述する場合には気をつけましょう、おしまい、いえ、まだ終わりません。

実はシングルトン以外にも、破棄する必要のないインスタンスがあって、それも大変身近な文字列クラス、NSString がそうです。
何をバカな、NSString の破棄が必要ないだなんて、そんなこと…はい、通常は当然必要なのですが、必要の無い NSString のインスタンスも存在するのです。まあ何か、大体もうお分かりでしょうけど、リテラル @"..." から生成されるインスタンスです。

そう、以下のようなコードは、問題なく動いてしまうのです。

void f(id obj) {
  [[[obj retain] autorelease] release]; /* oops */
}
NSString* str = @"...";
f(str); // ok...!!!

ギョエー!

追記:公開したつもりが下書きになっていました。もう Objective-C の季節は終わっています。