Created
May 4, 2024 13:40
-
-
Save omonien/9c7eae02c545dea2b805352c640a1da3 to your computer and use it in GitHub Desktop.
Demo of Delphi for loop that runs into an overflow, because of using non-matching types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program ForLoopOverflow; | |
{$APPTYPE CONSOLE} | |
{$R *.res} | |
uses | |
System.SysUtils; | |
begin | |
// Using unsigned ints or "short" types may lead to unexpected behaviour. | |
// This behaviour, such as "endless loops" is hidden, unless OVERFLOW checks are turned on | |
// In the scenario below only OVERFLOWCHECKS is relevant | |
// Both, RANGECHECKS and OVERFLOWCHECKS are turned on for DEBUG configurations from Delphi 11 | |
// General recommendation is to turn these two ON for DEBUG for legacy projects. | |
// You might end up with some surprising exceptions - which are NOT a Delphi bug, but are due to errors in your code | |
// that you hid away, and which may have caused some subtile bugs in your apps. | |
var j: cardinal; | |
//Using Integer or any other signed "large enough" int type would be safer w/o any checks. | |
//track what's happening | |
var LoopExecuted: boolean; | |
var LoopException: boolean; | |
{$RANGECHECKS ON} {$OVERFLOWCHECKS ON} | |
Writeln('Loop1 ...'); | |
LoopExecuted := false; | |
LoopException := false; | |
// Loop1 from 0 to -1 - should not execute by logic | |
j := 0; | |
try | |
for var i := 0 to j - 1 do | |
begin | |
LoopExecuted := true; // This should not execute | |
end; | |
except | |
on E: EIntOverflow do // This should raise | |
LoopException := true; | |
on E: Exception do | |
Writeln(E.ClassName, ': ', E.Message); | |
end; | |
try | |
Assert(LoopExecuted = false); | |
Assert(LoopException = true); | |
Writeln('Loop1 done. Not executed. Overflow Exception raised.'); | |
except | |
on E: Exception do | |
Writeln(E.ClassName, ': ', E.Message); | |
end; | |
{$RANGECHECKS OFF} {$OVERFLOWCHECKS OFF} | |
Writeln('Loop2 ...'); | |
LoopExecuted := false; | |
LoopException := false; | |
// Loop2: From 0 to -1 - should not execute by logic | |
j := 0; | |
try | |
for var i := 0 to j - 1 do | |
begin | |
LoopExecuted := true; // This WILL(!) execute | |
break; // break to avoid endless loop | |
end; | |
except | |
on E: EIntOverflow do // This should raise | |
LoopException := true; | |
on E: Exception do | |
Writeln(E.ClassName, ': ', E.Message); | |
end; | |
try | |
Assert(LoopExecuted = true); //The loop WILL execute! | |
Assert(LoopException = false); //NO exception will be raised! | |
Writeln('Loop2 done. Loop executed. No exception raised.'); | |
except | |
on E: Exception do | |
Writeln('Loop2: ' + E.ClassName, ': ', E.Message); | |
end; | |
readln; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment