iPhoneは、先進的なデザインやユーザーインタフェースによって、とてもパワフルな印象を受ける。だが、あくまでも携帯端末であり、やはり相応の小さい性能しか持っていない。

 その制約により、iPhoneでは、メモリー管理に「GC(ガベージコレクション)」を採用していない。GCの実行にはそれなりに大きなCPUパワーが必要となるからだ。

 代わりに、iPhoneではメモリー管理に「リファレンスカウンタ」方式を採用されている。オブジェクトのインスタンスがプログラム中の何カ所から参照されているかをカウントする方式で、リファレンスカウンタが1以上かどうかで、オブジェクトの生存か破棄かを判断する。

 この方式では、変数の中にインスタンスを保持しておく必要がある場合「retainメッセージ」を発行してカウンタを増やし、不要になったらインスタンスを解放するために「releaseメッセージ」を発行してカウンタを減らす。インスタンスを保持しているオブジェクトのことを「オーナー」といい、オーナーがいるうちはインスタンスは生き続ける。リファレンスカウンタが0になった(=オーナーが存在しなくなった)時にはじめて、インスタンスが破棄される。

 このように、カウンタによって不要になったオブジェクトを明示的に判断し、破棄するという方法をとることによって、余計なCPUパワーを使わずに、効率的にメモリー管理を行うことができる。

 リファレンスカウンタ方式はメモリー管理を効率的に行えるメリットがある半面、プログラマがそのカウンタの管理に注意してプログラミングする必要がある。そのため、不用意な実装をすると、オブジェクトを解放し損ねてメモリーリークを起こしてしまったり、まだ破棄してはいけないオブジェクトまで破棄してしまい、アプリケーションがクラッシュしてしまう可能性すらある。

 このような問題を回避するために、「オーナーシップポリシー」という規則にのっとってアプリケーションを開発すべきである。

 オーナーシップポリシーとは、「あるオブジェクトのオーナーになったオブジェクトは、そのオブジェクトの解放に責任も持つ」という取り決めのことだ。つまり、あるインスタンスに対してretainを発行したら、そのretainを発行したオブジェクト自身が、保持しているインスタンスのreleaseにも責任を持つ、ということだ。

 メモリーの管理でもう1点気をつけておきたいのは、releaseを行ったあとの変数に格納されたポインタの処理である。オブジェクトが格納されているメンバー変数には、オブジェクトの実体ではなく、そのポインタが保存されている(図1)。

図1●解放されたオブジェクトへのポインタを使うと不正アクセスになる
図1●解放されたオブジェクトへのポインタを使うと不正アクセスになる

 そのため、カウンタが0になって、あるオブジェクトが破棄された場合でも、元々そのオブジェクトを保持していた変数に入っているポインタは、そのまま破棄されたオブジェクトのあったメモリーアドレスを参照したままである。そのアドレスを利用すると、アプリケーションがエラーになる。

 エラーにならないようにするには、あるメンバー変数に格納されたインスタンスに対してreleaseを発行したら、それまでオブジェクトを保持していたメンバー変数に「nil」を代入することだ。そうすれば、不正なメモリーアクセスを回避できる。

 iPhoneのアプリケーションを作る際には、オブジェクトの状態について常に関心を配り、細かい注意を払って開発を進めていくように心がけよう。


亀本大地(かめもと だいち)
アシアル株式会社 エバンジェリスト
1981年生まれ。学生時代にPHPと出合い、その魅力に惹かれてアシアル株式会社に入社。それをきっかけに日本PHPユーザ会の運営にも参画するようになる。現在は、同社のWeb開発、スマートフォン開発を中心にしたシステム構築業務に従事し、特にiPhoneに関する執筆・講演なども多くつとめる。