Objective-CのPropertyの解放忘れを見つけるスクリプト

こんにちは、ちきん(@mokemokechicken)です。
最近は、iPhoneアプリの開発に携わっていまして、そこで「Objective-CのPropertyの解放忘れを見つけるスクリプト」を作ったのでご紹介します。
Objective-C で開発しているときに、一つ頭を悩ますのはメモリの解放周りです。
何に悩むかというと、以下の2パターンです。
(a) オブジェクトを解放し過ぎることによるアプリの異常終了
(b) オブジェクトを解放しないことによるメモリリーク
今回の話は(b)を発見する補助ツールのご紹介です。
何かのお役に立てば幸いです。


メモリリークは、アプリが落ちたりはしないので多少であればまだ許容できるのですが、
塵も積もれば・・・ということもあり、
ボディブローのようにいつかアプリのパフォーマンスに影響してくることも多いです。
私達は、オブジェクトを保持(retain)するときは、大抵property機能を使うことにしています。
しかし、そのpropertyでretainしたものは、 dealloc のときには必ず解放(release)しないといけないのですが、
結構大量にコードを書いているうちに、何かあとで付け足したりしているうちに忘れることが多いのです。
プロジェクトのソースファイルの数が1000個くらいになってくると、人力で全部調べるのは時間がかかり過ぎるので、
ちゃちゃっと調べるのが今回のスクリプトです。
ちなみに、もちろん完璧ではないので疑わしい部分を見つけるだけですが、
私のプロジェクトでは、約1000個ソースファイルがあって、50箇所くらい実際のrelease忘れが見つかりました。

使い方

python check_release.py <root_path> [<exclude_class_list_filename>]
root_path: ソースコードのルートディレクトリ。そこから再帰的に .m .mm .h ファイルを探します。
exclude_class_list_filename: もしチェックしたくないClassがあれば、このファイルに「1行に1クラス名」を書いて指定します。

動作の仕様

拙い英語ですが、
https://github.com/mokemokechicken/CheckRelease/blob/master/README
に書いてあるのでここでは省略します。

実行例

試しに、私たちのプロジェクトでも使用していて、公開されている iphone-rsdb に対して実行してみます。

# checkout tool
git clone git://github.com/mokemokechicken/CheckRelease.git
# checkout iphone-rsdb
hg clone https://code.google.com/p/iphone-rsdb/
# run tool
python CheckRelease/check_release.py iphone-rsdb
------------------------------------- 実行結果
ETYPE1: BooksTableViewController: [items] is not released?
ETYPE1: RSDBDatabase: [databaseURL] is not released?
ETYPE1: RSDBQuery: [table] is not released?
ETYPE1: RSDBRecord: [database] is not released?
ETYPE1: RSDBRecord: [table] is not released?
ETYPE1: RSDBTable: [database] is not released?
ETYPE1: RSDBTable: [tableName] is not released?
ETYPE1: RSDBTable: [primaryKeyColumnName] is not released?
-------------------------------------

ETYPE1というのが、解放忘れ?っぽい部分です。
後は本当に解放忘れなのか、誤検知なのか見ていけばOKというわけです。

Download

https://github.com/mokemokechicken/CheckRelease
からDownloadできます。


Comments are closed.