Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi 10.3 Rio - Is initializaiton of inline declared record variables needed?

I am quite excited about Delphi 10.3 Rio inline variable declarations. However I ran into strange problem and it seems that I need to initialize record after it has been inline declared:

program Project8;
{$APPTYPE CONSOLE}
{$R *.res}

uses System.SysUtils,classes;

procedure DoEvil;
  //var sr:TSearchRec; //A
begin
  //var sr:= default(TSearchRec); //B
  var sr:TSearchRec; //C
  sr.Name := EmptyStr; //D
  FindFirst('*.*',faAnyFile,sr);
  while sr.Name<>EmptyStr do
  begin
    Writeln(sr.name);
    sr.Name := EmptyStr;
    FindNext(sr);
  end;
end;

begin
  try
     DoEvil;
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

The code works fine if I declare sr on line:

  • //A (old style declaration) or on line
  • //B (inline declaration with initialization).

However if I declare sr on line

  • //C then it crashes on line //D, respective in system.pas on line 26222:

    MOV     ECX,[EDX-skew].StrRec.refCnt    { fetch refCnt                 }
    

with exception:

Exception class $C0000005 with message 'access violation at 0x0040ac98: read of address 0xfffffff9'. Process Project8.exe (18928)

I would assume from the address -6, that the string member sr.name is not initialized and is nil.

Just to be complete, Delphi is the new 10.3 release 1: Embarcadero® Delphi 10.3 Version 26.0.33219.4899 - Installed Update 1

like image 278
Radek Hladík Avatar asked Mar 04 '19 16:03

Radek Hladík


People also ask

What is inline variable declaration?

The new inline variable declaration syntax allows you to declare the variable directly in a code block (allowing also multiple symbols as usual): procedure Test; begin var I: Integer; I := 22; ShowMessage (I.


1 Answers

I took a look in the CPU window and found a few oddities.

If I use the old-style var-block (your version // A), the CPU window shows a call to System._InitializeRecord, as it should. All is fine and normal.

If I use the inline declaration with Default() (your version // B), the local record is nilled out, then finalized using System._FinalizeRecord and then nilled out again. That is pretty weird and useless, but it works.

But if I use your version // C, nothing is done to initialize the record: no nilling out, no _InitializeRecord. When I tested your code, things did work, but I was probably just lucky.

So this is clearly a bug. Please report it to the Embarcadero Quality Portal.


I guess this is a remainder of the changes made to the compiler when default constructors, default destructors and overloaded assignment operators were tested (but then removed and postponed to a next release). Some of these changes were rather braindead (like the nilling, finalization and nilling again, as in version B), and I guess some of these changes were forgotten.

Update

Obviously this was already reported to QP:

  • https://quality.embarcadero.com/browse/RSP-21632
  • https://quality.embarcadero.com/browse/RSP-23417
  • https://quality.embarcadero.com/browse/RSP-23747
like image 162
Rudy Velthuis Avatar answered Oct 11 '22 16:10

Rudy Velthuis