我对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