SlideShare uma empresa Scribd logo
1 de 44
Baixar para ler offline
CHAPTER06
ガーベジコレクション
不要なオブジェクトを探すには
ガーベジコレクションは実行中に不要になったメモリ領域を
発見し,自動的に解放する機能
不要なメモリを回収するルーチンをガベージコレクタ
と呼ぶ
不要なオブジェクトを探すには
ガベージコレクションは解放していないオブジェクトを
認識するところから始める
解放しないオブジェクト
外部変数,静的変数から参照されるオブジェクト
スタック内の変数から参照されるオブジェクト
これらのインスタンスをルート集合(root set)と呼ぶ
不要なオブジェクトを探すには
ルート集合に含まれるオブジェクト,および解放しては
いけないオブジェクトのインスタンス変数から参照される
オブジェクトも解放してはいけない
プログラム記述上の注意
右の例で,methodBをコメント
位置まで実行したとする
この時点でガベージコレク
ションが起きたとして,
回収される可能性のあるオブ
ジェクトを考える
id sharedObj = nil;
- (void)methodA {
id objA = [[Alpha alloc]init];
[objA doSomething];
}
- (void)methodB {
id objB = [[Beta alloc]init];
shareObj = [[Gamma alloc]init];
[self methodA];
shareObj = [[Zeta alloc]init;
/* ここまで実行したとすると? */
}
プログラム記述上の注意
スタック内にとられた変数objB
に代入されているオブジェクト
この時点ではobjBは有効なの
でオブジェクトは回収されな
い
id sharedObj = nil;
- (void)methodA {
id objA = [[Alpha alloc]init];
[objA doSomething];
}
- (void)methodB {
id objB = [[Beta alloc]init];
shareObj = [[Gamma alloc]init];
[self methodA];
shareObj = [[Zeta alloc]init;
/* ここまで実行したとすると? */
}
プログラム記述上の注意
外部変数shareObjには最初に
クラスGammaのインスタンス
が代入され,後からZetaのイン
スタンスが代入される
クラスGammaのインスタン
スはどこからも参照されてい
ないので回収の対象となる
id sharedObj = nil;
- (void)methodA {
id objA = [[Alpha alloc]init];
[objA doSomething];
}
- (void)methodB {
id objB = [[Beta alloc]init];
shareObj = [[Gamma alloc]init];
[self methodA];
shareObj = [[Zeta alloc]init;
/* ここまで実行したとすると? */
}
プログラム記述上の注意
methodAが呼び出されている
メソッド内の変数objAはメ
ソッドの実行が終われば無効
となる
クラスAlphaのインスタン
スも回収の対象となる
id sharedObj = nil;
- (void)methodA {
id objA = [[Alpha alloc]init];
[objA doSomething];
}
- (void)methodB {
id objB = [[Beta alloc]init];
shareObj = [[Gamma alloc]init];
[self methodA];
shareObj = [[Zeta alloc]init;
/* ここまで実行したとすると? */
}
プログラム記述上の注意
ガーベジコレクションではオブジェクトが不要になったかど
うかはガーベジコレクションが判断する
不要になったことを表す必要は無い
プログラム記述上の注意
カウンタ方式を利用する場合,オブジェクトを格納する
セッタメソッドでは次のように記述しなければならない
- (void)setHelper:(id)obj {
[obj retain]; // 引数の保持を必ず先に行う
[helper release]; // 元のオブジェクトを忘れずに解放
helper = obj;
}
プログラム記述上の注意
ガーベジコレクションの場合は以下のように記述
変数helperに入っていたオブジェクトが不要かどうかは
他から参照されているかどうかに基づいてガーベジコレク
ションが判断する
- (void)setHelper:(id)obj {
helper = obj;
}
ガーベジコレクタの動作
インスタンスオブジェクトの生成によって動的に割り当てられ
たメモリが一定量を超える
ガーベジコレクションはプログラムのスレッド内で動作し
不要となったオブジェクトを回収して解放する
回収と解放は必要に応じて自動的に繰り返される
ガーベジコレクタの動作
起動
停止
メモリの
消費量が多い
または
起動の要求
アプリケーション本体
ガーベジコレクタ
通常の実行
回収する
オブジェクトを
決定
回収対象の
オブジェクトに
finalizeを送信
回収対象の
オブジェクトの
メモリを解放
図:ガーベジコレクタの動作
ガーベジコレクタの動作
ガーベジコレクションはプログラム内に1つだけで,通常は
メインスレッドで動作する
ガーベジコレクタが動作している間,必要に応じて他の
スレッドが一時停止する事があるが,すべてが停止する事は
無い
ガーベジコレクタの動作
ガーベジコレクタはメモり消費状況を見て自動的に起動する
NSGarbageCollectorのインスタンスにメソッド
collectIfNeededを送る事により,ガーベジコレクションを
実行してほしい位置を示す事も出来る
ガーベジコレクタの動作
ガーベジコレクタによって回収されることになったオブジェクト
は直ちに解放される訳ではない
回収対象となるオブジェクトがすべて判明した後,
これらのオブジェクトにfinalizeというメッセージが送られる
すべてのオブジェクトでfinalizeの実行が終わってから,
メモリ領域は解放される
finalizeメソッドの定義
ガーベジコレクションによってインスタンスオブジェクトが
回収の対象となった場合
メソッドfinalizeが定義されていれば解放される前に
後処理を行う事が出来る
finalizeメソッドの定義
finalizeはNSObjectで定義されている
finalizeメソッドはサブクラスからスーパークラスの定義を
呼び出す場合以外,プログラム中に直接呼び出しては
いけない
- (void)finalize
{
... //なにか後始末をする
[super finalize];
}
finalizeメソッドの定義
finalizeメソッドの記述は次のことに注意しないといけない
1.finalize内で別のインスタンスを解放する心配はしない
オーナーシップに基づいて解放を考えてはいけない
不要になったオブジェクトはガーベジコレクタが
解放する
finalizeメソッドの定義
2.オブジェクトの代入に注意
finalizeメソッド内の自動変数以外に対してオブジェクト
を代入する事には気をつける
finalizeの実行中に別の変数に代入するなどして
回収されないようにする操作をレザレクションと呼ぶ
許されている言語もあるが,ObjCではエラーを
引き起こす
finalizeメソッドの定義
3.finalizeの実行順序,解放される順序は決まっていない
例えばオブジェクトAとBがあり,どちらも解放されると
する
このときどちらに先にfinalizeを送られるかは決まって
いない
finalizeメソッドの定義
4.finalizeはスレッドセーフでなければならない
スレッドセーフとは複数のスレッドが並列動作している
場合でも安全に実行できる事
特に複数のインスタンスが共有しているオブジェクト
や資源の扱いに注意が必要
コンパイル時の設定
ガーベジコレクションを使って動作するプログラムを作るには
コンパイルの際にオプションを設定する必要がある
オプション 意味 動作
なし サポートなし
カウンタ方式によるメモリ管理を行う
ガーベジコレクションは使わない
-fobjc-gc サポートあり
ガーベジコレクションとカウンタ管理方式による
メモリ管理の両方を使う
-fobjc-gc-only 必須 ガーベジコレクションだけを使う
カウンタ管理方式の記述との共存
ガーベジコレクションが有効の場合,リファレンスカウンタ
関係の以下のメソッドは定義されても動作しない
retain
release
autorelease
dealloc
retainCount
カウンタ管理方式の記述との共存
ガーベジコレクションの機能が追加されるに伴い
NSAutoreleasePoolに次のメソッドが設けられた
カウンタ管理方式の環境ではメソッドdrainはreleaseと
同様に機能する
ガーベジコレクションが有効な場合,ガーベジコレクショ
ンの開始を要求する
- (void)drain
ガーベジコレクションを使う
プログラムのまとめ
コンパイル時にオプション-fobjc-gc-onlyが必要
メソッドの実行中だけ使うオブジェクトはメソッド内の
自動変数に代入して使う
しばらくの間使うオブジェクトは外部変数から参照できる経
路を確保しておく
回収対象となるのはid型,クラスを指定した型を持つ変数のみ
ガーベジコレクションを使う
プログラムのまとめ
オーナーシップは意識しなくて良い.インスタンス変数の
面倒も見なくてよい
オブジェクトが解放されるときの後始末はfinalizeメソッドに
記述できるが,使わないですむように検討すべき
リファレンスカウンタ関係のメソッドおよびdeallocメソッド
は,プログラム中にあっても実行されない
世代別ガーベジコレクション
ガーベジコレクションを有効にしてコンパイルすると
id型やクラスを指定した型を持つ変数に対する代入,
変更操作を監視する実行コード(書き込みバリア)が
生成される
世代別ガーベジコレクション
ObjC2.0では変数の書き換え情報を利用して
世代別ガーベジコレクションと呼ばれる方式でメモリ管理を
おこなうようになっている
世代別ガーベジコレクション
世代別ガーベジコレクションでは
不要なオブジェクトを毎回徹底的に調べるのではなく,
通常は新しく生成されたインスタンスを中心に解放を行う
これにより処理の負担を軽減
同時に不要なオブジェクトを効果的に解放できる
数回に一回は詳しい検索を行う
‣ 不要なオブジェクトの蓄積を防ぐ
弱い参照
ObjC2.0では弱い参照という参照方法がある
通常の参照方法は強い参照と呼んで区別する
弱い参照
ガーベジコレクションでは,ルート集合から参照をたどって
到着できるオブジェクトは回収の対象としない決まり
弱い参照とはオブジェクトを参照するために使うものの,
ガーベジコレクションの回収対象とするかどうかには影響
しない参照
弱い参照
ガーベジコレクションを正確に言うなら
『ルート集合から強い参照だけをたどって到着できる
オブジェクトは回収対象とならない』
となる
ルート集合から参照する経路がまったくないか,
弱い参照を経由しないと到着できないオブジェクトは
ガーベジコレクションで回収の対象となる
弱い参照
弱い参照であることを示すには,
オブジェクトを格納する変数の定義に__weakという修飾子を
付加する
宣言の際に以下のように色々な位置に置く事も出来る
3番目の場合変数fの直前の__weakは省略できない
__weak id trmp;
__weak NSObject *cacheObj;
__weak NSObject *a, *b;
NSObject __weak *c, *d;
NSObject *__weak e, *__weak f;
変数のゼロ化
参照しているオブジェクトが突然なくなったら
そのオブジェクトを参照していた変数には無効になった
ポインタの値だけが残ってしまう
ぶらさがりポインタとなり,実行時にエラーの
原因となる
変数のゼロ化
強い参照の場合参照していたオブジェクトは
ガーベジコレクションで回収される事は無いので,
このような問題は発生しない
変数のゼロ化
弱い参照である事を宣言した変数は,
参照しているオブジェクトがガーベジコレクションによって
解放されるとき,自動的に空ポインタnilが代入される
これをゼロ化と呼ぶ
ガーベジコレクションで回収される
メモリ領域
オブジェクトではないメモリ領域を動的に確保し,
不要になったらガーベジコレクションで回収,解放するよう
にできる
メモリ領域を確保するには以下のような関数を利用する
引数のsizeにはバイト単位でメモリ領域の大きさを指定
第2引数のoptionsには必ず
定数NSScannedOptionsを指定する
void *__strong NSAllocateCollectable(
NSUInteger size, NSUInteger options);
メモリ管理方式の比較
ガーベジコレクションの利点
オブジェクトのオーナーシップを意識し続ける必要がなく
なる
プログラムからメモリ管理に関する記述を大半を
取り除けるため,見通しがよくなる
リファレンスカウンタの操作ミスによる問題(メモリリー
クなど)を起こす事が無い
メモリ管理方式の比較
リファレンスカウンタ特有のプログラミングパターンを
気にする必要がなくなる
マルチスレッドのプログラム記述が容易になる
オブジェクトの保持を行うアクセサは相互排除が
必要だったが,その必要がなくなった
メモリ管理方式の比較
ガーベジコレクションの欠点
ガーベジコレクタが動作するときにプログラムの
実行速度が低下する
カウンタ管理方式を用いたプログラムより速度が遅い
書き込みバリアや弱い参照のゼロ化などのコードが
プログラムに含まれるのが原因
メモリ管理方式の比較
メモリ効率の低下を招く
あまり使われていないメモリ領域にもガーベジコレクタ
が時々アクセスするため,実メモリをより多く占有する
ことによる
オブジェクトをガーベジコレクタによる回収の対象にする
または対象にしないために,新たに多少のテクニックが
必要になる
メモリ管理方式の比較
カウンタ管理方式で使ってきたいくつかの設計方針が
使えない
ファイルなどの資源を管理するオブジェクトを用意して
おき,オブジェクトが解放されると同時にファイルを
クローズするなど
おわり

Mais conteúdo relacionado

Mais de hasegawa

Cocoa Pro09
Cocoa Pro09Cocoa Pro09
Cocoa Pro09hasegawa
 
Cocoa Pro08
Cocoa Pro08Cocoa Pro08
Cocoa Pro08hasegawa
 
Cocoa Pro07
Cocoa Pro07Cocoa Pro07
Cocoa Pro07hasegawa
 
Cocoa Pro6
Cocoa Pro6Cocoa Pro6
Cocoa Pro6hasegawa
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5hasegawa
 
Cocoa Pro4
Cocoa Pro4Cocoa Pro4
Cocoa Pro4hasegawa
 
Cocoa Pro01
Cocoa Pro01Cocoa Pro01
Cocoa Pro01hasegawa
 
Cocoa Pro03
Cocoa Pro03Cocoa Pro03
Cocoa Pro03hasegawa
 
CocoaPro02
CocoaPro02CocoaPro02
CocoaPro02hasegawa
 

Mais de hasegawa (10)

Objc01
Objc01Objc01
Objc01
 
Cocoa Pro09
Cocoa Pro09Cocoa Pro09
Cocoa Pro09
 
Cocoa Pro08
Cocoa Pro08Cocoa Pro08
Cocoa Pro08
 
Cocoa Pro07
Cocoa Pro07Cocoa Pro07
Cocoa Pro07
 
Cocoa Pro6
Cocoa Pro6Cocoa Pro6
Cocoa Pro6
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5
 
Cocoa Pro4
Cocoa Pro4Cocoa Pro4
Cocoa Pro4
 
Cocoa Pro01
Cocoa Pro01Cocoa Pro01
Cocoa Pro01
 
Cocoa Pro03
Cocoa Pro03Cocoa Pro03
Cocoa Pro03
 
CocoaPro02
CocoaPro02CocoaPro02
CocoaPro02
 

Objc03 2