微软已经在 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)
解决方案
相反,您应该始终减去两个时间间隔:
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+}
, ) 上进行溢出检查时,两个滴答计数的减法会在TickCount翻转{$OVERFLOWCHECKS ON}
时生成 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}