メモリ管理の大まかな原則
C言語と共通の部分について、メモリ管理で気をつけることは特にありません。Cで気をつけることと共通です。 自分がmalloc()で確保したメモリは忘れずfree()で開放しましょうということだけです。従って、多くの場合に問題になるのはObjective-C固有の部分です。 Objective-Cのオブジェクトはretain countというものを持っています。生成すると0から1になります。 そのオブジェクトに関連付けられている変数名でretainをすれば、カウントが1増えます。 releaseをするとカウントが1減ります。run loopと呼ばれるシステムへの応答処理へ入った時、 このカウントが0になっているものはメモリ上から消えるようになっています。
autoreleaseとした場合には、適当と思われる部分で自動的に開放されるので、自分でreleaseを行う必要はありません。 便利そうに思えますが、自分が予期しないタイミングで実は開放されていたなどということも起きることがあるので、多用はしないほうが良いのかもしれません。 アップル社のiPhoneアプリケーション作成のガイドを見ても、autoreleaseはパフォーマンス上の理由でお勧めされていないようです。 さて、メモリ管理について、大雑把に原則を挙げると以下のようになります。
新たにローカルでメモリを割り当てたオブジェクトはreleaseする。
ただし+で始まるメソッドで確保されているものはそのままでよい。
メンバでプロパティがretainやcopyのオブジェクトはdeallocにreleaseを書いておく。assignはそのままで良い。
CF~で始まる関数で名前にCreateが入るもので作られたものはCFRelease()で開放する。
NSMutableArrayやNSMutableDictNSMutableArrayやNSMutableDictionaryに加えたローカルのオブジェクトはその後で開放する。
以下それぞれについて少しだけ細かく見てゆきます。
新たにローカルでメモリを割り当てたオブジェクトはreleaseする。
新たにローカルでallocを使いメモリを割り当てたオブジェクトは、そのオブジェクト名の有効範囲を超えない部分でreleaseをします。 ほとんどの場合、allocと組でinit~が書かれていると思いますが、これらはreleaseしないとメモリリークが起きます。
ただし+で始まるメソッドで確保されているものはそのままでよい。
APIリファレンスで-ではなく+で始まっているメソッドで割り当てられたメモリは、自動的にreleaseされるのでreleaseを記述する必要はありません。 先ほど出てきたalutoreleaseがセットされているからです。NSStringにはこの+で始まるものが多くあります。 これらのものはクラスメソッドと呼ばれています。これらを使う場合はallocを書くことは無いので簡単に区別ができるでしょう。 なおreleaseを書いてしまうと二重開放というものが起き、後からデバッグでエラーの原因を探すのに苦労します。
メンバでプロパティがretainやcopyのオブジェクトはdeallocにreleaseを書いておく。assignはそのままで良い。
プロパティがreainやcopyのオブジェクトは代入操作を行うときにメモリの割り当てが起こっているので、そのクラスがdeallocで消される時にreleaseします。
CF~で始まる関数で名前にCreateが入るもので作られたものはCFRelease()で開放する。
使用頻度はそれほど高くはないと思いますが、Core Foundationの命令を使う場合に当てはまる原則です。Createが入っているものはNS~のinit~と同じようなものなので、 NS~のreleaseに当たるCFRelease()を使って開放する必要があります。
NSMutableArrayやNSMutableDictionaryに加えたローカルのオブジェクトはその後で開放する。
ローカルで作成して、NSMutableArrayやNSMutableDictionaryにaddObjectやsetObjectなどで追加したオブジェクトは、 NSMutableArrayやNSMutableDictionary側で確保されているので、ローカルのオブジェクト名ではreleaseします。
メモリリークが起きていないかの確認方法
メモリリークが起きていないかはパフォーマンスツールを使うことで確認できます。Xcodeのメニューから実行 > パフォーマンスツールを使って、開始 > Leaksの順に選んでゆくと、今のビルド設定で開いているプロジェクトが実行されます。メモリリークが起きていれば下のグラフにオレンジの三角が見えるので、 そこをクリックして詳細を確認してゆけば、どのオブジェクトでリークが起きたか確認できます。詳細は下に並んでいるアイコンのうち、Object Summaryのすぐ左にあるものを押し、右側に階層表示をさせるとわかります。そのリストの中から自分のプロジェクト名で始まるものを探してダブルクリックすれば、 どこで割り当てたものかが判明するという仕組みです。これでわかるのはメモリへの割り当てが発生した部分なので、 その後そのオブジェクトがどんな変数へ渡されているかや、実際に開放すべきタイミングがいつだったのかは開発者が自分で考える必要があります。
なお、一度これを起動すると次にXcodeでビルドして進行を選ぶと毎回パフォーマンスツールが起動してしまいますが、メニューからビルド > ビルドとデバッグを選ぶと通常ビルドして進行を選んだときと同じ動作に戻ります。また、私の環境だけかもしれませんが、シミュレーターだと発生し、 実機では発生しないリークが検出されます。実機でリークなしに動くのであればおそらく問題はないでしょう。
前へ次へ