1 時間ほど、非常に不穏な動作について説明しようとしてきましたが、それが Visual Studio のコンパイラによるものなのか、デバッガによるものなのかは不明です。私は今、答えの一部を知っています。基本的に、MSVC2005 Debug ビルドで以下をコンパイルして実行しています。
DWORD timeStamp;
struct SomeEventStruct {
DWORD timeStamp;
// ... plus other data
};
void Magic( const SomeEventStruct & anEvent )
{
if ( anEvent.timeStamp < timeStamp )
{
ASSERT( false ); // shouldn't happen! Time does not run backwards!
}
timeStamp = anEvent.timeStamp;
}
ASSERT( false )
が実行できる唯一の方法は、if
式が true と評価される場合ですよね? では、なぜASSERT()
起動し、変数の値を検査するためにデバッガーに侵入したときに、 timeStamp
0 であることがよくあるのでしょうか? 定義上、これは不可能です。符号なしの値がゼロ未満になることはありません。
確かに、これはマルチスレッド アプリケーションですが、他のスレッドがこれらの変数に触れることはなく、すべてメイン UI スレッド内にあります。また、状況を単純化しました。実際には、それらはメンバー変数と関数であり、重要だとは思いません。私が関連していると信じているのは、最初にASSERT()
解雇され、デバッガーに侵入するように招待されたとき、変数の値が妥当であり、そこで悪いタイムスタンプが見つかったということです。物事が奇妙になり始めたのは、それを続けた後でした。
if
最終的に、ステートメントとステートメントの間で timeStamp 値がゼロにリセットされていることがわかりましたASSERT( false )
。これを行う可能性のある唯一のコード行は、最終的にタイマーイベントに接続されていることを知っています(上記のタイムスタンプ付きイベントとは異なります-タイマーは、興味のあるシステムイベントの表示を更新するために起動します)。
だから今私が知りたいのは、Windowsタイマーイベントが割り込みのように機能し、ある時点でスレッドの実行を中断し、後でそれに戻るか...またはVSデバッガーに固有の何かがここで起こっているか、またはの内部の仕組みASSERT()
?前の呼び出しが完了するまでタイマー イベント ハンドラーが実行されないようにしたい場合、その再入を防ぐのは私次第ですか?