森を見て木を見ないバグおとといのバグ。バグ自体はくだらないのだが、原因追究に無駄な時間を使ったのでメモ。次のようなプログラムを作った。...}が、テンプレートのパターンと引数に齟齬があり、例外が投げられるバグが見つかった(たとえば、{}内で特定の型を指定しているのに、引数がそれとは合わないなど)。そこで、以下のようにした。...}ところが、実際にはこの修正では引数の型指定がテンプレートと合わなければ修正前と同じことが起きる道理だ。したがって(実は予想もつかない引数を与えるやつがいるのが原因でやはり)例外が発生する(このメソッド自体が型をアンマーシャルするので、パラメータの型はobjectにせざるを得ないとか、いろいろ理由があって型はobject以外にできない)。このときReleaseモードでコンパイルしているため、メソッド名と行番号のみがバックトレースに入る。...ここですっかりだまされてしまった。FooBarがWriteを呼び出すのは、修正前のバージョンだ。修正後のバージョンであれば、Foo::FooBarとFoo::Writeの間にFoo::WriteAsABCDが呼ばれているはずだ。したがって、例外を起こしているプログラムは修正前のバージョンに違いない。調べても実行時に呼ばれているのは修正後のバージョンに見える。PATHにも間違いはなさそうだ(多分)。実行時にカレントディレクトリを変えているとか、そこがTemporaryでそこにバックアップされた古いプログラムが存在するとかか?だが、どう実行しても(実行環境は固有の環境で、デバッガなどは使えない。ネットワークから隔離されているのでリモートデバッガもあり得ない。開発環境は実行環境固有の環境を持ちえないので、開発環境でテストすることもあまり意味がない(ユニットテストとモックがあるわけだが、ここではそれをしていないのが大間違いだが、後の祭りである)例外になるし、バックトレースは上記の内容だし、実行しているのは修正後としか思えない。いうとき、何を疑うべきだろうか?もちろんソースコードを疑うべきだ。修正前のプログラムにバグがあるのはわかっている。瞬時にわからなかったのはしょうがないかなぁとは思うが、それにしても数分で気づけよとは思う。(実際には数十分かかった)これがトライ&エラーが簡単な環境ならば、printfデバッグですぐにわかるわけだが、それができないときは頭だけが頼りだな(いや、その前にユニットテストをちゃんと作っとけというのはあるけど)。