Objective-Cメモリ管理(1)

2011 年 4 月 11 日 by longSlife

Mac OS X/iPhone/iPadの主要プログラム言語Objective-Cで行うメモリ管理方法について
基本的部分からサンプルを作成しながら記録していきます。

Objective-Cでは、

1.リファレンスカウンタ方式
2.ガベージコレクション方式(Objective-C2.0より)

の2種類のメモリ管理方式を採用しています。

ただし、iPhone/iPadのiOSでは、リファレンスカウンタ方式のみとなっています。

リファレンスカウンタ方式は、
「インスタンスオブジェクトの使用者は、所有権保持要求(retain)し、不要になったときに所有権解放(release)要求します。

インスタンスオブジェクトは、所有権をカウンタで管理し所有者が誰もいなくなった(管理カウント値が0)時に、メモリ領域を解放します。」

リファレンスカウンタ方式の動作確認用プログラムと実行結果を以下に示します。

確認用クラスのインターフェース部

/**
*@file : OTester.h
*/
#import <Foundation/NSObject.h>

@interface OTester : NSObject
{
}
@end

確認用クラスの実装部

/**
*@file : OTester.m
*/
#import "OTester.h"

@implementation OTester

/**
*@brief : 生成
*/
+ (id)alloc
{
self = (id)[super alloc];
NSLog(@"alloc %d", (int)[self retainCount]);
return self;
}
/**
*@brief : 初期化
*/
- (id)init
{
self = [super init];
NSLog(@"init %d", (int)[self retainCount]);
return self;
}

/**
*@brief : 破棄
*/
- (void)dealloc
{
NSLog(@"dealloc %d\n", (int)[self retainCount]);
[super dealloc];
}

/**
*@brief : 所有権解放要求
*/
- (oneway void)release;
{
NSLog(@"release st %d\n", (int)[self retainCount]);
[super release];
NSLog(@"release ed %d\n", (int)[self retainCount]);
}

/**
*@brief : 所有権保持要求
*/
- (id)retain
{
[super retain];
NSLog(@"retain %d\n", (int)[self retainCount]);
return self;
}
@end

確認用テストプログラムMain部

/**
*@file : TestMain.m
*/
#import <stdio.h>
#import "OTester.h"

/**
*@brief : テストプログラム Main
*/
int main()
{
printf("---- Memory Manage Test Main Start -----\n");
//生成によりリファレンスカウンタが 1
id obj = [[OTester alloc] init];
// 所有権保持要求によりリファレンスカウンタが 1+1=2
[obj retain];<span> </span>
printf("****** release *****\n");
// 所有権解放要求によりリファレンスカウンタ 2-1=1
[obj release];
// 所有権解放要求によりリファレンスカウンタ 1-1=0
// リファレンスカウンタが0になりメモリ領域解放
[obj release];
// メモリ領域解放後に所有権解放要求を行うため実行時エラー
//    [obj release];<span> </span>// NG
printf("---- Memory Manage Test Main End -----\n");
return 0;
}

実行結果

---- Memory Manage Test Main Start -----
2011-04-03 21:36:38.604 OTester.out[534:903] alloc 1
2011-04-03 21:36:38.607 OTester.out[534:903] init 1
2011-04-03 21:36:38.607 OTester.out[534:903] retain 2
****** release *****
2011-04-03 21:51:32.959 OTester.out[565:903] release st 2
2011-04-03 21:51:32.960 OTester.out[565:903] release ed 1
2011-04-03 21:51:32.960 OTester.out[565:903] release st 1
2011-04-03 21:51:32.961 OTester.out[565:903] dealloc 1
2011-04-03 21:51:32.961 OTester.out[565:903] release ed 1
---- Memory Manage Test Main End -----

リファレンスカウンタが1->0(ログ上は0になっていない)時に破棄が行われdeallocが呼ばれています。

確認用テストプログラムMain部の「// [obj release]; // NG」行を有効にして実行させると、インスタンス破棄後のrelease要求を行った時の動作を確認できます。

テストプログラムのNG部を実行した結果

---- Memory Manage Test Main Start -----
...
2011-04-03 21:56:49.814 OTester.out[586:903] dealloc 1
2011-04-03 21:56:49.815 OTester.out[586:903] release ed 1
Segmentation fault

実体のないオブジェクトに対する要求で実行時エラーとなります。

つづく

タグ: ,

TrackBack