空想犬猫記

※当日記では、犬も猫も空想も扱っておりません。(旧・エト記)

メモリ再生系のバグ

今日は,久々に一日がかりの bug fix を行う。症状は

std::map<Object*,Data> _map;

みたいなオブジェクトがあって,オブジェクトに対応するデータをマップで管理しているんだけど,なぜかデータが,他の要素と入れ替わることがある,という気持ち悪いバグだった。基本ライブラリの機能なのだが

  1. 特定の製品でしか再現しない
  2. デバッグ版では再現しない

というおまけ付き。比較的新しいバグだったので

  1. 再現条件の絞り込み
  2. テストのログとコード修正履歴をレビュー
  3. printf(に類するもの)で _map をダンプしまくる

を3人で並列に取り組んで何とか問題を発見した。結局

  1. Object オブジェクトが,定期的に新しいポインタ値で入れ替わって,新しいエントリが作られる。Data はデータベースのキャッシュなので,新しいエントリに対応する Data はいつも正しい
  2. 古いオブジェクトが delete されても,エントリがメンテされず,ゴミポインタ値とデータのエントリが残る
  3. ときどき,以前 delete された Object オブジェクトと全く同じポインタ値のオブジェクトが作られ,古いエントリを乗っ取ってしまう

というバグだった。ポインタ値は単なる map のキーとしてしか使われていなかったので,クラッシュもせず,発見が遅れてしまっていたようだ。結局 Object の削除を抽象的に observe する仕組みを使って,map を更新する方法で修正。

メモリ破壊ならぬ「メモリ再生」バグ。ちょっと新鮮。