さて、allocなんかも使ってみたことだし、噂の参照カウント値を見てみよう。
#import <Foundation/Foundation.h>#import "1.h"
int main(void){Hell *hell = [[Hell alloc] init];NSLog(@"count = %ld\n", [hell retainCount]);
[hell print];NSLog(@"count = %ld\n", [hell retainCount]);
[hell release];NSLog(@"count = %ld\n", [hell retainCount]);
return 0;
}
printfでもいいけど、そろそろNSLogってのにも慣れておかねば。
$ clang -o tst 1.m main.m -lobjc -framework Cocoa
$ ./tst
+[Hell initialize]
hell init!
2013-06-16 13:30:40.503 tst[791:707] count = 1
hell print : 10
2013-06-16 13:30:40.505 tst[791:707] count = 1
2013-06-16 13:30:40.505 tst[791:707] count = 1
うーん・・・。
releaseしようとすまいと、1だな。。。
gccでもそうだったのでclangにしてみたのだが、それでも同じだ。
(-framework Cocoa、がついたのは、NSLogがリンクエラーになるため。)
ratainすると2になり、次にreleaseすると1になる。
でも、今みたいにretainしなくても、releaseしたら1のままだ。
続けてreleaseすると、落ちる。
うーむ・・・・・・・。
そもそも、デフォルトの場合はARCが有効なのだろうか? 無効なのだろうか?
コンパイルオプションに「-fobjc-arc」をつけるとARC有効、「-fno-objc-arc」をつけるとARC無効。
まずは-fno-objc-arcをつけてみる。。。変化無し。
では、-fobjc-arcをつけると・・・コンパイルエラーだ!
つまり、デフォルトではARC無効でコンパイルされるようだ。
エラーの内容は「ARCが有効だとretainCountは参照できんよ」というもの。
あと、retainとreleaseもだめだって。
では、ちょっとソースを変えて試していこう。
//[1.h]
#import <Foundation/Foundation.h>@interface Hell : NSObject- (void)print;
@end--------------------//[1.m]
#import <stdio.h>#import "1.h"
static int gValue;@implementation Hell//
+ (void)initialize
{printf("%s\n", __FUNCTION__);
if (self == [Hell class]) {printf("hell init!\n");
gValue = 10;}}- (id)init{printf("%s\n", __FUNCTION__);
return self;
}- (void)dealloc
{printf("%s\n", __FUNCTION__);
}//
- (void)print
{printf("hell print : %d\n", gValue++);
}@end--------------------//[main.m]
#import <Foundation/Foundation.h>#import "1.h"
void func(Hell *hell)
{[hell print];NSLog(@"%s end\n", __FUNCTION__);
}int main(void){Hell *hell = [[Hell alloc] init];func(hell);NSLog(@"%s end\n", __FUNCTION__);
return 0;
}
$ clang -o tst 1.m main.m -lobjc -framework Cocoa -fobjc-arc
$ ./tst
+[Hell initialize]
hell init!
-[Hell init]
hell print : 10
2013-06-16 14:00:20.938 tst[858:707] func end
2013-06-16 14:00:20.940 tst[858:707] main end
-[Hell dealloc]
mainで確保したhellが解放されるのは、mainを抜けたときだ。
では、ちょっと差し替えよう。
//[main.m]
#import <Foundation/Foundation.h>#import "1.h"
void func(void){Hell *hell = [[Hell alloc] init];[hell print];NSLog(@"%s end\n", __FUNCTION__);
}int main(void){func();NSLog(@"%s end\n", __FUNCTION__);
return 0;
}
$ clang -o tst 1.m main.m -lobjc -framework Cocoa -fobjc-arc
$ ./tst
+[Hell initialize]
hell init!
-[Hell init]
hell print : 10
2013-06-16 14:03:34.217 tst[864:707] func end
-[Hell dealloc]
2013-06-16 14:03:34.218 tst[864:707] main end
funcで確保したhellは、funcを抜けた後で解放される。
じゃあ、これならどうだ?
#import <Foundation/Foundation.h>#import "1.h"
static Hell *hell;
void func(void){hell = [[Hell alloc] init];[hell print];NSLog(@"%s end\n", __FUNCTION__);
}int main(void){func();NSLog(@"%s end\n", __FUNCTION__);
return 0;
}
$ clang -o tst 1.m main.m -lobjc -framework Cocoa -fobjc-arc
$ ./tst
+[Hell initialize]
hell init!
-[Hell init]
hell print : 10
2013-06-16 14:05:07.479 tst[872:707] func end
2013-06-16 14:05:07.480 tst[872:707] main end
確保はfunc()でやってるけど、変数スコープがグローバルなので解放するタイミングがない。
まあ、これはmain抜けたらプロセスごと終わるからいいんだろうけど、強制的に解放したいときがあるかもしれない。
#import <Foundation/Foundation.h>#import "1.h"
static Hell *hell;
void func(void){hell = [[Hell alloc] init];[hell print];NSLog(@"%s end\n", __FUNCTION__);
}int main(void){func();NSLog(@"%s end\n", __FUNCTION__);
hell = nil;return 0;
}
$ clang -o tst 1.m main.m -lobjc -framework Cocoa -fobjc-arc
$ ./tst
+[Hell initialize]
hell init!
-[Hell init]
hell print : 10
2013-06-16 14:07:28.059 tst[880:707] func end
2013-06-16 14:07:28.060 tst[880:707] main end
-[Hell dealloc]
hellにnilを突っ込むことで結合が切れ、mainを抜けたタイミングで解放される処理が呼ばれた、というところか?
いや、そうではないようだ。
nilを代入する時点で解放が呼び出されていた。
mainのNSLog()前で代入すればそこでdeallocが呼ばれたし、func()で代入すればそこで呼ばれた。
そうなっているんだ、というくらいしか言えることはありませんな。
あとは、プロパティとかプロトコルみたいな基本を押さえて、今日は終わりにしますかな。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。