私は最近、私たちの製品に不具合を修正しました。逆Heisenbug - デバッガが接続されている場合にのみユニットテストが失敗する
私はバグが戻ってこないように単体テストを追加しました。ユニットテストを書くとき、私はいつも私の欠陥修正を取り消し、ユニットテストが失敗するのを確実にします。そうでなければ、それが適切に仕事をしていないことを知っています。
欠陥修正を取り消した後、私は単体テストがまだ合格していないことを発見しました。なぜそれが合格するのかを見るためにユニットテストにデバッガをつけたところ、テストは失敗しました(例外がスローされました)。私はブレークして、コールスタックが私が修正した元の欠陥のものと一致しているのを観察しました。
Visual Studio 2005で "Break on exception"設定を変更していませんでした。これは実際にはテストハーネスを終了させる重要なWin32例外です(優雅な例外ハンドラはありません)。
例外のテキストは次のとおり
Unhandled exception at 0x0040fc59 in _testcase.exe: 0xC0000005:
Access violation reading location 0xcdcdcdcd.
注:位置は常に0xcdcdcdcd
(allocated but unwritten Win32 heap memory)ではありません。場合によっては0x00000000
であり、別のアドレスであることもあります。
これは伝統的なHeisenbugの逆のように見えますが、デバッガを使ってそれを観察すると問題が解消されます。私の場合は、デバッガを介してそれを観察すると、問題が表示されます!
私が最初に考えたのは、これはデバッガのタイミングの違いによって明らかになった競合状態でした。しかし、コードにトレースを追加してデバッガとは別に実行したときに、私が出力しているデータは、デバッガで実行しているときと同様の方法でアプリケーションを中止する必要があることを示しています。そうではありません!
これを引き起こす可能性のあることについてのご意見はありますか?
アップデート:私はこの問題の原因にで狭めています。詳細はthis questionを参照してください。見つけたらこの質問を答えに更新します。
デバッガが接続されたときにプログラムがクラッシュしたような楽しいバグがありました。私は最後に、 'sem_wait'の呼び出しでブロックされたスレッドがあることを知りました。デバッガは接続時にスレッドを中断し、 'sem_wait'をエラーEINTRで返します。その後、スレッドは実行を続け、Bad Things Happenedを実行しました。言うまでもなく、私はエラーコードをチェックすることが重要である理由を学びました... –