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
