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