Hatena::Groupiphone-dev

iPhoneアプリ開発まっしぐら★ このページをアンテナに追加 RSSフィード

引っ越し後の日記はコチラです

tokoromのその他の日記

2009-07-06

NSStringのretainCountが異常な値になる件

23:22 | はてなブックマーク - NSStringのretainCountが異常な値になる件 - iPhoneアプリ開発まっしぐら★

paellaさんの記事(http://iphone-dev.g.hatena.ne.jp/paella/20090706/1246874977)に便乗して記事を書かせていただきます。


retainCountのテストをしているとき、NSStringのオブジェクトのretainCountが「2147483647」になってびっくりしたものです。※後述しますがretainCountが「-1」になるケースもあります

これってじつは参照カウンタが「2147483647」というよりは、オブジェクト定数だから解放しなくてもいいよというのを表す「NSIntegerのMAX値」だったのです。retainCountはreleaseされる度にデクリメントされて、これが0になるとメモリ自体が解放されるというカウンタの役割をしているのですが、文字列定数なんかは解放不要のものとしてretainCountとして「NSIntegerMax」を返すという規定みたいです。

このへんの話に近いことが、Appleの「NSObject Protocol Reference」にも記載されています。そこには「オブジェクトが解放しちゃいけないものなら、retainCountの戻り値はUINT_MAXにしろ」と書いてあります。

ちなみにiPhone SDK3.1ではUINT_MAXという定義は存在せず、NSUIntegerMax(-1)を使います。同じドキュメントには明記されていませんが、実際の挙動を確認すると、オブジェクト定数の場合にはNSUInteger(-1)の代わりにNSIntegerMax(2147483647)を返すみたいです。

以下、実験したコードです。

  NSString* message = [NSString stringWithString:@"MESSAGE"];
  NSLog( @"retainCount = %d", [message retainCount] ); //< retainCount = 2147483647

  NSNumber* num = [NSNumber numberWithBool:YES];
  NSLog( @"retainCount = %d", [num retainCount] ); //< retainCount = 2147483647

  NSString* blank = [[NSString alloc] autorelease];
  NSLog( @"retainCount = %d", [blank retainCount] ); //< retainCount = -1

同じ"MESSAGE"という文字列を保持していても、NSStringの実体が文字列定数でなければretainCountも通常どおりのものになります。

  NSString* utf8 = [NSString stringWithUTF8String:"MESSAGE"];
  NSLog( @"retainCount = %d", [utf8 retainCount] ); //< retainCount = 1

paellapaella2009/07/09 00:56私の拙い説明に的確なフォローをしていただいてありがとうございました。オブジェクト定数の場合は-1ではなかったんですね。

きちんと確認しなければ、と反省しています。