さて、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 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。