Delphi: How to avoid EIntOverflow underflow when subtracting?
- by Ian Boyd
Microsoft already says, in the documentation for GetTickCount, that you could never compare tick counts to check if an interval has passed. e.g.:
Incorrect (pseudo-code):
DWORD endTime = GetTickCount + 10000; //10 s from now
...
if (GetTickCount > endTime)
break;
The above code is bad because it is suceptable to rollover of the tick counter. For example, assume that the clock is near the end of it's range:
endTime = 0xfffffe00 + 10000
= 0x00002510; //9,488 decimal
Then you perform your check:
if (GetTickCount > endTime)
Which is satisfied immediatly, since GetTickCount is larger than endTime:
if (0xfffffe01 > 0x00002510)
The solution
Instead you should always subtract the two time intervals:
DWORD startTime = GetTickCount;
...
if (GetTickCount - startTime) > 10000 //if it's been 10 seconds
break;
Looking at the same math:
if (GetTickCount - startTime) > 10000
if (0xfffffe01 - 0xfffffe00) > 10000
if (1 > 10000)
Which is all well and good in C/C++, where the compiler behaves a certain way.
But what about Delphi?
But when i perform the same math in Delphi, with overflow checking on ({Q+}, {$OVERFLOWCHECKS ON}), the subtraction of the two tick counts generates an EIntOverflow exception when the TickCount rolls over:
if (0x00000100 - 0xffffff00) > 10000
0x00000100 - 0xffffff00 = 0x00000200
What is the intended solution for this problem?
Edit: i've tried to temporarily turn off OVERFLOWCHECKS:
{$OVERFLOWCHECKS OFF}]
delta = GetTickCount - startTime;
{$OVERFLOWCHECKS ON}
But the subtraction still throws an EIntOverflow exception.
Is there a better solution, involving casts and larger intermediate variable types?