[Tips] やっぱりObj-C1.0のメモリ管理がクソな件
やってらんねー.
Objective-C 2.0からやっとガーベッジコレクションがついたObj-Cシリーズだが.
やっぱりだめだ.iPhoneのランタイムはObj-C1系統だし,以前のランタイムでビルドしたバイナリはガーベッジコレクションに対応していないので,管理・非管理に気をつけないといけない.
だりぃ.
(さ)さんから,質問がありましたが,ザッと説明するとこんな感じ?
Obj-Cはインスタンスが保持カウンタを持っています.
p = [[HogeClass alloc] init];
こうすると,pの保持カウンタは1です.
allocでインスタンスを生成,initで初期化という意味です.
この保持カウンタが0になると,pは,解放されます.
つまり,あるメソッドの中で上の様にインスタンスを作成した場合は,releaseをしないといけないのです.
void hoge() { id p = [[HogeClass alloc] init]; [p release]; }
こうすると,pは,hogeが実行し終わったタイミングで解放されます.
ここまでは,フーーーーーーーンなんですが.
Obj-Cには,autorelease機能があります.
void hoge() { id pool = [[NSAutoreleasePool alloc] init]; id p = [[[HogeClass alloc] init] autorelease]; [pool release]; }
void hoge() { id pool = [[NSAutoreleasePool alloc] init]; id p = [NSString stringWithString:@"hoge"]; [pool release]; }
クラスメソッドでインスタンスを生成すると,そのインスタンスに自動的にautoreleaseが送られます.上二つの両方とも,poolが解放されると同時にpは解放されます.
インスタンスにautoreleaseを送ると,NSAutoreleasePoolにそのインスタンスが登録されます.
そして,そのNSAutoreleasePoolのインスタンスが解放されるときに,自動的に登録されているインスタンスそれぞれにreleaseが送られます.
Cocoaでプログラミングするときは,NSApplicationMainのメインイベントループから抜けるときにautoreleaseしたオブジェクトにreleaseが送られます.
※以下,追記修正
どうやら,僕は,今まで勘違いしており,
>イベントループ内で毎回生成されるNSAutoreleasePool
>は、ループが一回転するごとに解放されるので、基本
>的にこれに登録されたオブジェクトに割り当てられた
>メモリはイベント処理が終わると解放される。
これをループの外で呼んでいると思っていたところにあったようです.
しかも,実際にイベントごとにメモリの挙動を調べてみると,あるメソッド終了後に解放されているように一見,見える.これは,ループが一回転したときに解放されていることだったのですね・・・・・.無知で恥ずかしい.
つまりこういうわけだ.
while() { // メッセージループ id pool = [[NSAutoreleasePool alloc] init]; // process [pool release]; }
しかし,別にメモリ管理がやりやすいわけではないぞ.
結局参照じゃ保持カウンタは,増えないわけで,自前でreleaseしてやらないといけない.
しかも,やったことはないけど,絶対マルチスレッドで参照とかやったら,相当めんどくさいことになると思う・・・.
※間違いがあったら,ツッコミお願いします.