iOSでのメモリの管理
iOSで使われるデータの種類にはint型やchar型などのプリミティブな型のほか,NSStringやNSArrayなどのオブジェクト型がある.
int型やchar型などはC言語の仕様を引き継ぎ,メモリ領域のスタック領域に確保されるため,とくにメモリを管理するコードは必要ない.
オブジェクトはヒープと呼ばれるところからメモリ領域を借りてきてそこにデータを保持する.
ヒープ領域を使う場合は,明示的に必要なサイズを確保し,使用済みとなった場合は明示的に領域を戻す必要があるので,
オブジェクトのメモリ管理には慎重になる必要がある.
参照カウンタ方式
iOSではオブジェクトのメモリ管理に参照カウンタ(reference counting)方式を採用している.
オブジェクトを使用時には,そのオブジェクトに対してretainメッセージを送信する.
すると,そのオブジェクトの保持カウンタ(retain counter)を1増える.
使用済みとなったらそのオブジェクトに対してreleaseメッセージを送信すると,保持カウンタが1減る.
保持カウンタは参照されるオブジェクトが管理しており,この値が0になった場合にオブジェクトは自身に
deallocメッセージを送信する.
deallocメッセージが送信されたオブジェクトは自身をヒープ領域から消滅させ,ヒープから借用していたサイズを戻す.
A B
NSString *str = [[NSString alloc] init];
strオブジェクトが生成され,保持カウンタは1.
[str retain];
Bによりstrがretainされ,保持カウンタは2.
[str release];
Bによりstrがreleaseされ,保持カウンタは1.
[str release];
Aによりstrがreleaseされ,保持カウンタは0.
この時点でstrの利用が0になり,strは自身にdeallocを送信.
ヒープにメモリが返される.
autorelease pool
Objective-Cではautorelease poolというオブジェクトの保持カウンタをある時点で自動で減らす仕組みがある.
autorelease poolは,あとでまとめてreleaseしたいオブジェクトを登録しておくためのオブジェクトである.
autorelese poolに登録されたオブジェクトは,autorelease poolオブジェクトが破棄されたタイミングで,
まとめてreleaseされる.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc init]; NSString *str = [[NSString alloc] initWithString:@"hello"]; [str autorelease]; // strのreleaseを予約する ... NSArray *ary = [[NSArray alloc] initWithArray: ....]; [ary autorelease]; // aryのreleaseを予約する ... [pool release]; // この時点でstrとaryにreleaseが送信される
autorelease poolがよく利用されるのはオブジェクトを作成し,そのポインタを返すための"簡易メソッド"である.
see more @http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/11/index.html
参照カウンタ方式利用時のルール
- オブジェクトを生成する際にはalloc/copy/newする.この時点で自動的に保持カウンタは1となる
- 自分以外が生成したオブジェクト利用時にはretainして明示的に利用する.
- alloc/copy/new/retainしたオブジェクトは,使用後に必ずreleaseする.
autorelease poolに登録しても可. - 自分以外が生成したオブジェクトで,retainもていない場合(オーナーではない),絶対releaseしない.
- initWith~で始まる簡易メソッドは,オブジェクトを生成しそのアドレスを返すメソッドであり,
通常,内部でautorelease poolを使っている.この場合,不用意にreleaseをしない.