プログラミング系のネタをまとめていきます。

メモリ管理方式


Cocoa環境のObjective-Cで用意されているメモリ管理方式。
  • リファレンスカウンタ
  • ARC(Automatic Reference Counting)
  • ガーベジコレクション (Objective-C 2.0 移行。iOSでは使えない)

NSObject


NSObjectクラスには、メモリ管理に関連するメソッドが定義されている。
alloc, init, retain, release, dealloc 等。

リファレンスカウンタ

例1


(1)オブジェクトA が alloc + init でインスタンス生成(リファレンスカウンタ=1)

    オブジェクトA    →    (インスタンス)          オブジェクトB


(2)オブジェクトBがインスタンスを参照する(リファレンスカウンタ=1)

    オブジェクトA    →    (インスタンス)    ←    オブジェクトB


(3)オブジェクト1がインスタンスの参照をやめる(リファレンスカウンタ=0)
    オブジェクトA          (インスタンス)    ←    オブジェクトB


(4)インスタンスが開放されるが、オブジェクトBはインスタンスが存在していたメモリを参照したまま。
    オブジェクトA          (            )    ←    オブジェクトB

例2


(1)オブジェクトA が alloc + init でインスタンス生成(リファレンスカウンタ=1)

    オブジェクトA    →    (インスタンス)          オブジェクトB


(2)オブジェクトBがインスタンスを参照し、retainを呼ぶ(リファレンスカウンタ=2)

    オブジェクトA    →    (インスタンス)    ←    オブジェクトB


(3)オブジェクト1がインスタンスの参照をやめる(リファレンスカウンタ=1)
    オブジェクトA          (インスタンス)    ←    オブジェクトB


(4)インスタンスのリファレンスカウンタが残っているので、インスタンスは破棄されずに残っている(ルファレンスカウンタ=1)
    オブジェクトA          (インスタンス)    ←    オブジェクトB

オーナーシップ


オブジェクトがインスタンスをalloc+initしたり、retainを送ってカウンタをインクリメントすることで、
そのインスタンスを保持(retain)していることになる。

インスタンスを保持することを、 「オーナーシップを持っている」 という。

テストプログラム


// NSObjectを継承する
@interface MyObj: NSObject
{
}

// イニシャライザ -(id)new という書き方もある
-(id)init;

-(void)dealloc;
@end

@implementation MyObj
-(id)init
{
    printf("MyObj init\n");
    return self;
}

-(void)dealloc
{
    printf("MyObj dealloc\n");
    [super dealloc];
}
@end


{
    MyObj* obj = [[MyObj alloc] init];
    printf("retainCount 0 : %d\n", (int)[obj retainCount]);
    
    [obj retain];
    printf("retainCount 1 : %d\n", (int)[obj retainCount]);
    
    [obj release];
    printf("retainCount 2 : %d\n", (int)[obj retainCount]);

    [obj release];
}


●実行結果
MyObj init
retainCount 0 : 1
retainCount 1 : 2
retainCount 2 : 1
MyObj dealloc

安全なアクセッサメソッド


オーナーシップを持つ場合の注意点について。

-(void)setMyValue:(id)obj
{
	[myValue release];
	myValue = [obj retain];		// ← myValue同じインスタンスが渡された場合、上のreleaseで解放されてしまうことがある。
}

●対策
//例1
-(void)setMyValue:(id)obj
{
	[obj retain];		// リファレンスカウンタを先に増やしておく
	[myValue release];	// 上記対応で、ここで解放されることがなくなる
	myValue = obj;
}

//例2
-(void)setMyValue:(id)obj
{
	if(myValue != obj)
	{
		[myValue release];
		myValue = [obj retain];
	}
}

自動解放プール


NSAutoreleasePool を使うと、後でまとめてインスタンスへreleaseメッセージを送ることが出来る。
前述の MyObj を使った例。

●サンプルコード
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];	// 自動解放プール開始

	MyObj* obj = [[MyObj alloc] init];
	[obj autorelease];	// 自動解放プールへ登録

	[pool drain];		// 自動解放プール終了
}


●実行結果
MyObj init
MyObj dealloc

一時的なインスタンスの生成


NSString のメソッド
メソッド説明所有者
-(id) initWithUTF8Stringallocで生成したインスタンスに対するイニシャライザ。生成したオブジェクトがインスタンスのオーナー
+(id) stringWithUTF8String一時的なインスタンスを生成するメソッドオーナー無し。自動解放プールに登録される。

●メソッドの命名規則
allocのイニシャライザは init〜
一時的なインスタンスを生成するメソッド、文字列は string〜、配列は array〜 という感じ。

書籍


タグ

Menu

メインコンテンツ

プログラミング

機器

Macツール

各種情報

Wiki内検索

おまかせリンク

Androidアプリ

AdSense

技術書


管理人/副管理人のみ編集できます