Skip to content

Instantly share code, notes, and snippets.

@satoshin2071
Last active April 2, 2021 21:59
Show Gist options
  • Save satoshin2071/c99400015b95060d4e63 to your computer and use it in GitHub Desktop.
Save satoshin2071/c99400015b95060d4e63 to your computer and use it in GitHub Desktop.
CoreFoundation入門 メモリ管理

#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にも同じルールがある。

  1. 関数名に「Create」という文字があったらオーナーシップを持つ
  2. 関数名に「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オブジェクトの代入は、危険を伴うので最大限の注意をもって実装すべし。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment