Delphi:如何避免EIntOverflow下溢?
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) 解决方案 相反,您应该总是减去两个时间间隔: 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呢? 但是当我在Delphi中执行相同的数学运算时,通过溢出检查({Q},{$OVERFLOWCHECKS ON}),当TickCount翻转时,减去两个滴答计数会产生EIntOverflow异常: if (0x00000100 - 0xffffff00) > 10000 0x00000100 - 0xffffff00 = 0x00000200 这个问题的解决方案是什么? 编辑:我试图暂时关闭OVERFLOWCHECKS: {$OVERFLOWCHECKS OFF}] delta = GetTickCount - startTime; {$OVERFLOWCHECKS ON} 但减法仍然会抛出一个EIntOverflow异常. 有更好的解决方案,涉及铸件和更大的中间变量类型? 更新 另一个问题是我问,为什么{$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} 解决方法
这样一个简单的功能呢?
function GetElapsedTime(LastTick : Cardinal) : Cardinal; var CurrentTick : Cardinal; begin CurrentTick := GetTickCount; if CurrentTick >= LastTick then Result := CurrentTick - LastTick else Result := (High(Cardinal) - LastTick) + CurrentTick; end; 所以你有 StartTime := GetTickCount ... if GetElapsedTime(StartTime) > 10000 then ... 只要StartTime和当前GetTickCount之间的时间小于GetTickCount的臭名昭着的49.7天范围,它将会工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |