objective-c の autorelease の動き

C# のガベージコレクションと同じなのかなぁ、と思ったけど、動き的には c++ のスマートポインタに近いのかな。
autorelease を指定すると、NSAutoreleasePool のオブジェクトに溜め込まれるようです。ここで、間違って release してしまうと落ちてしまう(core dump)ので、alloc と release の対応は、malloc/free, new/delete 並に厳しいコーディングをしないと駄目ですね。
一律、autorelease を使って release を使わないで記述するか、autorelease を使わずに release 自体をまめにコーディングしていくか悩むところ。

UIImage のように大きめなメモリを取得するものは、autorelease にするとメモリを占有してしまうので、release をするってのが適当ですね。

/*
export INCLUDE=/GNUstep/System/Library/Headers
export LIB=/GNUstep/System/Library/Libraries
export CFLAGS='-fconstant-string-class=NSConstantString  -enable-auto-import'

gcc -o main main.m -lobjc -lgnustep-base -I $INCLUDE -L $LIB $CFLAGS
*/
#import <stdio.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>

@interface Hello: NSObject
{
	@private
	NSString *_msg ;
}
@end

@implementation Hello
- (void)setMessage:(NSString*)msg 
{
	_msg = msg;
}
- (void)print
{
	// NSLog( _msg );
	printf("%s\n", [_msg cString]);
}
- (void)dealloc
{
	NSLog( @"in dealloc" );
	[super dealloc];
}
@end

int _main(int argc, char *argv[])
{
	puts("hello obj-c world.");

	// autorelease を使った場合
	Hello *hello = [[[Hello alloc] init] autorelease];
	[hello setMessage:@"hello objective-c in hello class"];
	[hello print];
	
	// autorelease を使わない場合
	Hello *hello2 = [[Hello alloc] init];
	[hello2 setMessage:@"hello objective-c no autorelease"];
	[hello2 print];
	[hello2 release];
	
	return 0;
}

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = _main(argc, argv);
	NSLog(@"before pool release");
    [pool release];	// ここで一気に解放される
	NSLog(@"after pool release");
    return retVal;
}

実行結果

$ main
hello obj-c world.
hello objective-c in hello class
hello objective-c no autorelease
2011-07-05 15:46:23.484 main[4124] in dealloc
2011-07-05 15:46:23.545 main[4124] before pool release
2011-07-05 15:46:23.545 main[4124] in dealloc
2011-07-05 15:46:23.545 main[4124] after pool release
カテゴリー: 開発, Objective-C パーマリンク