The following code to compare two Real48's (6-byte float) compiles and runs, but either generates non-nonsensical results or generates a AV.
program Project44;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Generics.Defaults;
begin
try
WriteLn(System.Generics.Defaults.TComparer<Real48>.Default.Compare(100.0,100.0));
WriteLn('all ok, press space');
except on E:exception do
WriteLn(e.Message);
end;
ReadLn
end.
It should output 0, but if it does not bomb first it outputs -92
or some other incorrect value.
Is this bug still present in the lastest XE8?
And if so, has it been reported before, I cannot find anything on the https://quality.embarcadero.com, but if there's an older QC I would like to refer to that.
Finally....
How do I compare two REAL48
types using TComparer<something>
?
EDIT :
this was the fix I settled upon:
interface
...snip...
[Test]
procedure TestReal48;
...snip...
TTest<T> = record
private
class var Def: System.Generics.Defaults.IComparer<T>;
class var F: FastDefaults.TComparison<T>;
public
class function Real48Comparison(const Left, Right: T): Integer; static;
implementation
procedure TestDefault.TestReal48;
var
OldDef: System.Generics.Defaults.IComparer<Real48>;
begin
OldDef:= TTest<Real48>.Def;
TTest<Real48>.Def:= System.Generics.Defaults.TComparer<Real48>.Construct(TTest<Real48>.Real48Comparison);
TTest<Real48>.Test(100.0,100.0);
TTest<Real48>.Test(100000.0,-10000.0);
TTest<Real48>.Test(0.0,-10000.0);
TTest<Real48>.Test(100000.0,0.0);
TTest<Real48>.Test(0.0,0.0);
TTest<Real48>.Def:= OldDef;
end;
This defect is present in all versions of the compiler. Since
Real48
was deprecated more than a decade ago I would expect that Embarcadero would not change the behaviour, even if you submitted a bug report. Of course, you should still submit a bug report, but I would not hold your breath when waiting for a fix!You'll have to construct a comparer rather than relying on the default:
Why does the default
Real48
comparer fail so hard. Well, it starts here:It transpires that
TypeInfo(Real48)
yieldsnil
. There would appear to be no type info available forReal48
. Probably not a great surprise.Then we reach here:
We take the
else
branch and callComparer_Selector_Binary
. So we end up performing a binary comparison. The comparison is actually performed by this function:which calls:
Not going to be useful for a real valued type.
As for the runtime error that relates to the ABI for
Real48
. It seems thatReal48
parameters are always passed on the stack. That is just not compatible with the use of untyped parameters inCompare_Binary
.