Microsoft は、GetTickCount のドキュメントで、ティック カウントを比較して間隔が経過したかどうかを確認することはできないと既に述べています。例えば:
不正解 (疑似コード):
DWORD endTime = GetTickCount + 10000; //10 s from now
...
if (GetTickCount > endTime)
break;
上記のコードは、ティック カウンターのロールオーバーの影響を受けやすいため、不適切です。たとえば、クロックがその範囲の終わりに近づいているとします。
endTime = 0xfffffe00 + 10000
= 0x00002510; //9,488 decimal
次に、チェックを実行します。
if (GetTickCount > endTime)
GetTickCount
はよりも大きいため、これはすぐに満たされendTime
ます。
if (0xfffffe01 > 0x00002510)
ソリューション
代わりに、常に 2 つの時間間隔を減算する必要があります。
DWORD startTime = GetTickCount;
...
if (GetTickCount - startTime) > 10000 //if it's been 10 seconds
break;
同じ数学を見ると:
if (GetTickCount - startTime) > 10000
if (0xfffffe01 - 0xfffffe00) > 10000
if (1 > 10000)
コンパイラが特定の方法で動作する C/C++ では、これはすべてうまくいきます。
しかし、Delphi はどうでしょうか。
しかし、( {Q+}
, ) のオーバーフロー チェックを使用して Delphi で同じ計算を実行すると、 TickCountがロールオーバー{$OVERFLOWCHECKS ON}
すると、2 つのティック カウントの減算により EIntOverflow 例外が生成されます。
if (0x00000100 - 0xffffff00) > 10000
0x00000100 - 0xffffff00 = 0x00000200
この問題の意図した解決策は何ですか?
編集:一時的にオフにしようとしましたOVERFLOWCHECKS
:
{$OVERFLOWCHECKS OFF}]
delta = GetTickCount - startTime;
{$OVERFLOWCHECKS ON}
しかし、減算は依然としてEIntOverflow
例外をスローします。
キャストとより大きな中間変数型を含む、より良い解決策はありますか?
アップデート
私が尋ねた別のSOの質問では、なぜ{$OVERFLOWCHECKS}
うまくいかないのかを説明しました。どうやら、行レベルではなく、関数レベルでのみ機能します。したがって、以下は機能しませんが:
{$OVERFLOWCHECKS OFF}]
delta = GetTickCount - startTime;
{$OVERFLOWCHECKS ON}
以下は機能します:
delta := Subtract(GetTickCount, startTime);
{$OVERFLOWCHECKS OFF}]
function Subtract(const B, A: DWORD): DWORD;
begin
Result := (B - A);
end;
{$OVERFLOWCHECKS ON}