メモリリークは開発者の最大の敵の一つだ。
それは得てしてうっかりミスで起こってしまうことがほとんどだが、今回検証したプログラムでは正直自分のミスかどうかはよくわからない。
iOSのバグの可能性も考えたくなる。

色々と調べてみたが、stackoverflowにも似た事例は無いし、自分の調査では原因はよくわからなかった。
しかし、一応解決方法らしきものは見つかったのでまとめておこうと思う。
 
メモリリークが起きる条件
これはシンプルで、配列でappend()を呼んだ際に起きた。
と言っても条件付きだ。

まずは以下のソースを見て欲しい。

いたってシンプルな作りだ。
オリジナルのTestDataクラスを作り、配列にインスタンスを一つ追加しているだけ。
これでメモリリークが起こるなどとは思えない。

しかし、起こるのだ。
Leaksをスクリーンショットを貼っておく。
memory-leak01
ご覧のようにappend()で起きている。

次にこの現象が起きる端末を調べてみたところ、起きる端末と起きない端末が存在することがわかった。
例えば、シミュレータではiPhone5(8.4)やiPad2(8.4)では発生したが、iPhone6(8.4)やiPadAir(8.4)では発生しなかった。

シミュレータ特有の問題かと思い実機で試したところ、iPodTouch5(8.4)では発生したが、iPhone6 Plus(8.4)では発生しなかった。

原因は全くわからないが、幾つかの回避方法を発見したので紹介しておく。

回避方法その1:TestDataを構造体にする
現在クラスとして定義しているTestDataを構造体にしてみたところ、メモリリークは発生しなくなった。
しかし、構造体は継承が使えないので、この方法では困ることもあるだろう。

回避方法その2:メンバ変数を追加する
以下のようにTestDataクラスにメンバ変数を追加してみた。

これで実行するとメモリリークは発生しなかった。
ただし、intParamの定義場所は重要であるようだ。

このようにした場合は相変わらずメモリリークは発生した。

結論
iOS側のバグの可能性も捨てきれないが、実際に一部の端末でメモリリークが起きている以上、見過ごすわけにはいかない。
それが原因でリジェクトされたら、顧客に文句を言われるのは開発者である我々なのだ。

原因がよくわからない以上、対策としてはこまめにLeaksでチェックして、メモリリークが起きていたら上記の対応を行う等で凌ぐしかない。
その場凌ぎにすぎず気持ち悪いが、現状では致し方ない。