overflow/range error not detected by delphi
overflow/range error not detected by delphi
I had code as follows:
Q.ParamByName('iID').AsInteger := lNextID;
lNextID is defined as Int64, but I used the AsInteger (which is type
Integer - ie 32-bits large), but even with Overflow and Range Checking
enabled (and a total project rebuild), Delphi never complained or hinted that I made a mistake or that data could be truncated. Weird??
Subsequently I changed the code to .AsLargeInt := lNextID;
I'm using Delphi 10.2.2 and it's a 32-bit Windows project.
I had code as follows:
Q.ParamByName('iID').AsInteger := lNextID;
lNextID is defined as Int64, but I used the AsInteger (which is type
Integer - ie 32-bits large), but even with Overflow and Range Checking
enabled (and a total project rebuild), Delphi never complained or hinted that I made a mistake or that data could be truncated. Weird??
Subsequently I changed the code to .AsLargeInt := lNextID;
I'm using Delphi 10.2.2 and it's a 32-bit Windows project.
Delphi type "system" is an ad hoc year-by-year mix of safe and fast, rigorous and permissive bag of artifacts with little unifying idea, if any. You just have to memorize things.
ReplyDeleteIt is not hard to explain in retrospect, though. Due to performance reasons of 1980-s it was always so for Int8 (byte) and Int16(integer) in the original Turbo Pascal years. LongInt back then internally was a set of TWO int16 vars. With Delphi 2.0 the native integer type was extended to Int32, but behavior remained. Both to keep source-level compatibility and to avoid re-writing the already working compiler parts. With Delphi XE2 the native integer type was extended yet again (for Win64 platform), now to Int64. but the behavior was kept for the same reasons: compatibility with the vast body of already written code plus performance.
So, if you dig a bit into the history you may quite expect it. And in retrospect it is clear and obvious.
Or you can just memorize things.
Delphi never checked between conversions of integer types (Integer, Longint and Int64 are all integer types). Can you imagine how many hints you would get? The whole source is riddled with integer conversions. AsInteger is actually a LongInt in IBX (and I expect in other Datasets too). Also see stackoverflow.com - Delphi compile-time integer conversion warnings?
ReplyDeleteThanks for the info. Following the link provided and reading the comments, it seems most developers would prefer an option in Delphi to actually tell you about such issues at compile time. It seems like quite a logical thing to expect. Yet more feature requests by actual developers going unheard by EMBT, and instead we get given more useless IDE themes and such.
ReplyDeleteThere is a range check happening but it depends on what is in the int64. If that fits into an int32 everything is fine, otherwise you get a range error.
ReplyDeleteSee this code:
var
i: Integer;
i2: Int64;
begin
{$RANGECHECKS ON}
i2 := High(Integer);
i := i2;
Writeln(i);
Inc(i2);
i := i2; // <- boom
Writeln(i);
end.
FWIW: FPC also does not give any hint at compiletime - see http://forum.lazarus-ide.org/index.php?topic=42568.0
Stefan Glienke : Unfortunately, you are wrong regarding your FPC comment. FPC has support for warning the developer of such mistakes. Simply add the dedicated -CO compiler parameter. Here it shows the compiler warning:
ReplyDelete$ fpc -CO -vh overflow.pas
Hint: Start of reading config file /home/graemeg/.fpc.cfg
Hint: End of reading config file /home/graemeg/.fpc.cfg
Free Pascal Compiler version 3.0.4+dfsg-18ubuntu2 [2018/08/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling overflow.pas
overflow.pas(11,7) Hint: Type size mismatch, possible loss of data / range check error
Linking overflow
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
14 lines compiled, 0.0 sec
3 hint(s) issued
Graeme Geldenhuys Interesting, now please also tell the people on the Lazarus forums - they might be more interested than me ;)
ReplyDeleteWill do, I just didn't want more false information spread. Fake news and all. ;-)
ReplyDeleteIn Go there are no implicit conversions between numeric types. I would welcome this feature in the Delphi compiler.
ReplyDeletetour.golang.org - A Tour of Go
Maybe advanced records can be used to inhibit comversions?
ReplyDeleteThere was some lib, that used A.R. to move back Extended (10 bytes x87 floating point) into Delphi Win64 compiler