Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi    [ Add a report in this area ]  
Report #:  121590   Status: Closed
[Win32] NativeUInt in Variant leads to ERangeError (32bit Windows only)
Project:  Delphi Build #:  19.0.14356.6604
Version:    19.0 Submitted By:   Krystian Bigaj
Report Type:  Crash / Data loss / Total failure Date Reported:  1/7/2014 2:32:02 AM
Severity:    Critical / Show Stopper Last Updated: 4/15/2014 7:07:49 PM
Platform:    All versions Internal Tracking #:   46463
Resolution: Fixed (Resolution Comments) Resolved in Build: : XE6
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: 10
Description
NativeUInt value is stored in Variant (as type varLongWord=19 - on x86). When you want to assign such Variant to NativeUInt compiler generates call to VarToInteger (instead of VarToInt64, like when using Longword).

When NativeUInt is larger than MaxInt then you get ERangeError.

It's important to me, because our application is build with:
{$SetPEFlags $20} // LARGE_ADDRESS_AWARE

Due to this issue, FireDAC crashes with ERangeError somewhere on casting Variant->NativeUInt to objects when there is > 2GB memory allocated (in my test mode for 32bit app 4GB compatibility under Win x64). Of course it's not FireDAC fault.

This leads to unable to use LARGE_ADDRESS_AWARE with FireDAC...

Delphi XE5 Update 2:
- 32 bit - ERangeError
- 64 bit - works fine
Steps to Reproduce:
Run attached example project (Target 32-bit Windows).
---------
function TestOK(v: Variant): LongWord;
begin
  Result := V; // Calls VarToInt64
end;

function TestERROR(v: Variant): NativeUInt;
begin
  Result := V; // Calls VarToInteger --> ERangeError
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  OK: LongWord;
  ERR: NativeUInt;
begin
  OK := $FFFFFFFF;
  OK := TestOK(OK);

  ERR := $FFFFFFFF;
  ERR := TestERROR(ERR);
end;
---------
Workarounds
None
Attachment
121590.zip
Comments

Krystian Bigaj at 1/7/2014 9:41:31 AM -
This report should be in Language/Variants, however I've somehow missed that subcategory.

Krystian Bigaj at 1/8/2014 2:16:42 AM -
It looks like problem was since at least D2009 (12.0.3420.21218), however I haven't used then FireDAC/AnyDAC so bug didn't show up for me.

Krystian Bigaj at 3/21/2014 12:03:16 AM -
Patch to make FireDAC work with {$SetPEFlags $20} (LARGEADDRESSAWARE) in x86 app running on x64 OS:
- Open FireDAC.DApt
- Find TFDDAptTableAdapter.MatchRecordSet
- Replace:
      oTab := TFDDatSTable(NativeUInt(ATable));
  with:
      // FD Workaround: http://qc.embarcadero.com/wc/qcmain.aspx?d=121590
      // NOTE: TFDDatSTable(Cardinal(ATable)) - will NOT WORK CORRECTLY !
      oTab := TFDDatSTable(Int64(ATable));

Note: You can get here ERangeError only, when you app will allocate at least 2GB of virtual memory or when TFDDatSTable will be allocated on memory above 2GB. You can simulate it with FastMM and with defined AlwaysAllocateTopDown in project. Don't forget to add {$SetPEFlags $20} into .dpr

@Sysop: And as you can see, not only NativeUInt leads to ERangeError, but ALSO Cardinal (in some cases)! I'm not sure why sometimes compiler generates for Cardinal(Variant) call to VarToInt64, and sometimes VarToInteger. In this case ATable is declared as: const ATable: Variant

Krystian Bigaj at 3/21/2014 12:16:14 AM -
'Mystery' solved, in this case, using Longword/Cardinal leads to ERangeError:

function TestERROR_Longword(const v: Variant): Longword;
begin
  Result := Longword(TObject(Longword(V))); // Calls VarToInteger !!!
end;

TestERROR_Longword(Longword($FFFFFFFF));
TestERROR_Longword(Longword(MaxInt)+1);

@Sysof: In this case also x64 compiler is affected!

Krystian Bigaj at 4/15/2014 1:46:34 AM -
I've just tested it on trial version of XE6 (20.0.15596.9843) and it does not fix it. Both compilers are still affected: x86 and x64.

Tomohiro Takahashi at 4/15/2014 7:24:54 AM -
Thanks for the confirmation. I will check the internal status of this report...

Tomohiro Takahashi at 4/15/2014 7:07:42 PM -
>   Result := V; // Calls VarToInteger --> ERangeError
This issue is fixed with Delphi XE6 using attached project.

So, if you still have  any issues, please put new QC report.

Krystian Bigaj at 3/27/2014 12:52:54 PM -
@Sysop: I see that it's already "Checked In". Does this fix covers also my recent comment - mainly that Win64 is also affected?

Krystian Bigaj at 7/27/2014 1:16:59 PM -
Continuation of this QC:
http://qc.embarcadero.com/wc/qcmain.aspx?d=126335

Server Response from: ETNACODE01