加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi:如何避免EIntOverflow下溢?

发布时间:2020-12-15 09:52:49 所属栏目:大数据 来源:网络整理
导读:Microsoft已经在GetTickCount的文档中说过,你永远不会比较滴答计数来检查间隔是否已经过去.例如.: 不正确(伪代码): DWORD endTime = GetTickCount + 10000; //10 s from now...if (GetTickCount endTime) break; 上面的代码是坏的,因为它是可接受的滚动计
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天范围,它将会工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读