メモリ再生系のバグ
今日は,久々に一日がかりの bug fix を行う。症状は
std::map<Object*,Data> _map;
みたいなオブジェクトがあって,オブジェクトに対応するデータをマップで管理しているんだけど,なぜかデータが,他の要素と入れ替わることがある,という気持ち悪いバグだった。基本ライブラリの機能なのだが
- 特定の製品でしか再現しない
- デバッグ版では再現しない
というおまけ付き。比較的新しいバグだったので
- 再現条件の絞り込み
- テストのログとコード修正履歴をレビュー
- printf(に類するもの)で _map をダンプしまくる
を3人で並列に取り組んで何とか問題を発見した。結局
- Object オブジェクトが,定期的に新しいポインタ値で入れ替わって,新しいエントリが作られる。Data はデータベースのキャッシュなので,新しいエントリに対応する Data はいつも正しい
- 古いオブジェクトが delete されても,エントリがメンテされず,ゴミポインタ値とデータのエントリが残る
- ときどき,以前 delete された Object オブジェクトと全く同じポインタ値のオブジェクトが作られ,古いエントリを乗っ取ってしまう
というバグだった。ポインタ値は単なる map のキーとしてしか使われていなかったので,クラッシュもせず,発見が遅れてしまっていたようだ。結局 Object の削除を抽象的に observe する仕組みを使って,map を更新する方法で修正。
メモリ破壊ならぬ「メモリ再生」バグ。ちょっと新鮮。