Delphi 10.3 Rio-是Initiaizaiton的Initizaiton所需的记录变量



我对Delphi 10.3 Rio内联变量声明感到非常兴奋。但是,我遇到了奇怪的问题,似乎我需要在记录被宣布之后初始化记录:

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.

如果我在线上声明SR,则该代码正常运行:

  • //a(旧样式声明)或在线上
  • //b(初始化的内联声明)。

但是,如果我在线上声明SR

  • //c然后它在行//d上崩溃,在System.PAS中分别在第26222行中:

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

例外:

异常类$ c0000005带有消息的访问违规行为 0x0040ac98:读取地址0xfffffff9'。Process Project8.exe(18928)

我会从地址-6中假设,字符串成员sr.name不是初始化的。

为了完成,Delphi是新的10.3版本1:Embarcadero®Delphi10.3版本26.0.33219.4899-安装更新1

我在CPU窗口中浏览了一些奇怪的地方。

如果我使用旧风格的var-block(您的版本// A),则CPU窗口显示了对System._InitializeRecord的调用。一切都很好。

如果我使用Default()(您的版本// B)使用内联声明,则本地记录将被删除,然后使用System._FinalizeRecord完成最终确定,然后nilled Out 再次。这很奇怪且毫无用处,但它有效。

但是,如果我使用您的版本// C可以完成记录的初始化:没有nilling out of Out,则没有_InitializeRecord。当我测试您的代码时,事情确实有效,但是我可能很幸运。

,这显然是一个错误。请将其报告给Embarcadero质量门户。


i 猜测这是对编译器进行的剩余更改的剩余时间,当测试了默认的构造函数,默认的破坏者和超载分配运算符(但随后删除并推迟到下一个版本)。其中一些变化相当脑力(例如nilling,cinteral和nilling of nill,如版本B中),我想其中一些变化被遗忘了。

更新

显然,这已经报告给QP:

  • https://quality.embarcadero.com/browse/rsp-21632
  • https://quality.embarcadero.com/browse/rsp-23417
  • https://quality.embarcadero.com/browse/rsp-23747

最新更新