その他
    ホーム 技術発信 DoRuby Objective-C + Cocoaにおけるメモリ管理について

    Objective-C + Cocoaにおけるメモリ管理について

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    こんにちは。

    KBMJの佐藤です。

    今回はObjective-CでCocoaアプリケーションを作る際における

    メモリ管理について解説します。

    http://farm4.static.flickr.com/3280/2987292642_b6d5e38a07.jpg

    MyObject.h

    #import <cocoa /cocoa.h>
    
    // (1)
    @interface MyObject : NSObject {
    }
    
    // (2)
    -(void)dealloc;
    
    @end
    

    MyObject.m

    #import "MyObject.h"
    
    @implementation MyObject
    
    // (3)
    -(void)dealloc
    {
    	NSLog(@"MyObject dealloc");
    	[super dealloc];
    }
    
    @end
    

    Memory.m

    #import <foundation /foundation.h>
    #import "MyObject.h"
    
    int main (int argc, const char * argv[]) {
        // (4)
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
        // (5)	
        MyObject* object1;
        object1 = [[MyObject alloc] init];
        [object1 release];
    
        // (6)
        MyObject* object2;
        object2 = [[[MyObject alloc] init] autorelease];
    
        // (7)	
        NSString* string0;
        string0 = [NSString stringWithCString:"new string" encoding:NSASCIIStringEncoding];
    
        // (8)	
        NSString* string1;
        string1 = [[[NSString alloc] initWithCString:"new string" encoding:NSASCIIStringEncoding] autorelease];
    
        // (9)	
        NSLog(@"before pool release");
        [pool release];
        NSLog(@"after pool release");
    
        return 0;
    }
    

    コード解説(1)

    @interface MyObject : NSObject {
    }
    

    MyObjectクラスを宣言します。

    NSObjectを親クラスとします。

    コード解説(2)

    -(void)dealloc;
    

    deallocメソッドを宣言します。

    このメソッドはインスタンス解放時に呼び出されます。

    コード解説(3)

    -(void)dealloc
    {
    	NSLog(@"MyObject dealloc");
    	[super dealloc];
    }
    

    deallocメソッドを実装します。

    NSLog関数にてメッセージを出力し、

    親クラスであるNSObjectのdeallocを呼び出します。

    コード解説(4)

        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    

    NSAutoreleasePoolのオブジェクトを作成する。

    この後に自動開放指定されたオブジェクトについては、

    [pool drain] の時点で解放されます。

    コード解説(5)

        MyObject* object1;
        object1 = [[MyObject alloc] init];
        [object1 release];
    

    MyObjectオブジェクトのためのメモリを確保、

    オブジェクトを初期化し、

    解放します。

    コード解説(6)

        MyObject* object2;
        object2 = [[[MyObject alloc] init] autorelease];
    

    MyObjectオブジェクトのためのメモリを確保、

    オブジェクトを初期化し、

    自動開放指定します。

    このオブジェクトは [pool drain] された時点で解放されます。

    コード解説(7)

        NSString* string0;
        string0 = [NSString stringWithCString:"new string" encoding:NSASCIIStringEncoding];
    

    NSStringオブジェクトのためのメモリを確保、

    オブジェクトを初期化し、

    自動開放指定します。

    コード解説(8)

        NSString* string1;
        string1 = [[[NSString alloc] initWithCString:"new string" encoding:NSASCIIStringEncoding] autorelease];
    

    NSStringオブジェクトのためのメモリを確保、

    オブジェクトを初期化し、

    自動開放指定します。

    stringWithCString を用いる場合に比べてコードが冗長になりますので、

    こういった場合は stringWithCString を呼び出した方が良いでしょう。

    コード解説(9)

        NSLog(@"before pool release");
        [pool release];
        NSLog(@"after pool release");
    

    NSAutoreleasePoolオブジェクトを解放する。

    自動開放指定されたオブジェクトはこのタイミングでまとめて解放されます。

    実行ログ

    2008-10-30 12:15:01.597 Memory[6684:10b] MyObject dealloc
    2008-10-30 12:15:01.598 Memory[6684:10b] before pool release
    2008-10-30 12:15:01.599 Memory[6684:10b] MyObject dealloc
    2008-10-30 12:15:01.600 Memory[6684:10b] after pool release
    

    自動開放指定したオブジェクトが

    [pool release] したタイミングで、

    まとめて解放されていることが分かります。

    さいごに

    Objective-C + Cocoa のような参照カウント方式のメモリ管理では

    オブジェクトの生存期間を意識しながらコードを書いていく必要があるかと思います。

    次回以降、Objective-C や Cocoa に関する記事を掲載していきたいと思います。

    お楽しみに!

    個人ブログ 拡張現実ライフ