9

我对 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 行崩溃,分别在第 26222 行的 system.pas 中:

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

除了:

异常类 $C0000005 带有消息“0x0040ac98 的访问冲突:读取地址 0xfffffff9”。处理 Project8.exe (18928)

我会从地址 -6 假设字符串成员 sr.name 未初始化并且为零。

完整地说,Delphi 是新的 10.3 版本 1:Embarcadero® Delphi 10.3 版本 26.0.33219.4899 - 已安装更新 1

4

1 回答 1

6

我查看了 CPU 窗口,发现了一些奇怪的东西。

如果我使用旧式 var-block(您的版本// A),CPU 窗口会显示对 的调用System._InitializeRecord,因为它应该。一切都很好,很正常。

如果我将内联声明与Default()(您的版本// B)一起使用,则本地记录将被取消,然后使用最终确定System._FinalizeRecord,然后再次取消。这很奇怪而且没用,但它确实有效。

但是,如果我使用您的版本// C,则不会对记录进行任何初始化:不删除,不_InitializeRecord。当我测试你的代码时,事情确实有效,但我可能只是幸运。

所以这显然是一个错误。请向Embarcadero 质量门户报告。


这是在测试默认构造函数、默认析构函数和重载赋值运算符时对编译器所做的其余更改(但随后被删除并推迟到下一个版本)。其中一些变化相当脑残(比如 nilling、finalization 和 nilling,就像在版本 B 中一样),我想其中一些变化被遗忘了。

更新

显然,这已经报告给 QP:

于 2019-03-04T18:18:46.913 回答