#CoreFoundation入門 メモリ管理
##概要
CoreFoundationのルートクラス的存在であるCFTypeの中から一番使用するであろう、メモリ管理関連のメソッドを確認。
##リファレンスカウント方式のメモリ管理
CoreFoundationはObjective-Cと同様の生成/保持/解放のリファレンスカウント方式。生成したらオーナーシップを持ち、必要なくなったらオーナーシップを破棄するのが必須なのも一緒。
NSObject *obj = [[NSObject alloc]init];
[obj retain] //参照カウント2
[obj release] //参照カウント1
[obj release] //参照カウント0 解放
// CFTypeで確認するのは面倒なのでCFStringRefで
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault,
"Core Foundation",
kCFStringEncodingUTF8);
CFRetain(str); // 参照カウント2
CFRelease(str) //参照カウント1
CFRelease(str) //参照カウント0
##クリエイトルール
Objective-Cではcopy,mutableCopy,new,init**というメソッドはretainCountが1のインスタンスを返すのと同様にCoreFoundationにも同じルールがある。
- 関数名に「Create」という文字があったらオーナーシップを持つ
- 関数名に「Copy」という文字があったらオーナーシップを持つ
※上記のCFStringCreateWithCString関数とかがいい例。
##Toll-free bridge
FoundationのAPIでオーナーシップをもったあとCoreFoundationで解放することは可能。勿論その逆も可能。NSMutableArrayオブジェクトを生成し、CoreFoundationオブジェクトとして解放できるか確認。
int main(int argc, const char * argv[]) {
CFMutableArrayRef cfObj = NULL;
{
// 変数objがオブジェクトへの強い参照 rc + 1
id obj = [[NSMutableArray alloc]init];
// __bridge_retainedによりobjをCFRetainしてcfObjに代入したとみなせるので rc + 1
cfObj = (__bridge_retained CFMutableArrayRef)obj;
CFShow(cfObj);
// rc は 2
printf("retin count = %ld\n", CFGetRetainCount(cfObj));
}
// 変数objがスコープを超えて強い参照が消滅したので rc は 1
printf("retain count after the scope = %ld\n",CFGetRetainCount(cfObj));
// 破棄
CFRelease(cfObj);
return 0;
}
実行結果
(
)
retin count = 2
retain count after the scope = 1
Program ended with exit code: 0
問題なく使用できている。
今度は反対にCFMutableArrayRefを生成しObjective-Cのオブジェクトとして扱えるかを確認。
int main(int argc, const char * argv[]) {
// rc + 1
CFMutableArrayRef cfObject = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
// 当然 rc 1
printf("retain count = %ld\n", CFGetRetainCount(cfObject));
// (__bridge_transfer id)により変数objの強い参照とCFReleaseによる解放が同時に発生
id obj = (__bridge_transfer id)cfObject;
// 変数objのみが参照をもっているので rc 1
printf("retain count after the cast = %ld\n", CFGetRetainCount(cfObject));
// objはまだ生きている
NSLog(@"class=%@", obj);
return 0;
}
実行結果
retain count = 1
retain count after the cast = 1
2014-11-12 18:13:34.514 CoreFoundationSample[35823:303] class=(
)
Program ended with exit code: 0
C言語のポインタ型変数などへのObjective-Cオブジェクトの代入は、危険を伴うので最大限の注意をもって実装すべし。