Delphi 10.3 Rio - 是否需要对内联声明的记录变量进行初始化?
Delphi 10.3 Rio - Is initializaiton of inline declared record variables needed?
我对 Delphi 10.3 Rio 内联变量声明感到非常兴奋。但是我 运行 遇到了 st运行ge 问题,似乎我需要在记录被内联声明后初始化它:
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 }
有例外:
Exception class $C0000005 with message 'access violation at
0x0040ac98: read of address 0xfffffff9'. Process Project8.exe (18928)
我假设从地址 -6 开始,字符串成员 sr.name 未初始化并且为 nil。
补充一下,Delphi 是新的 10.3 版本 1:
Embarcadero® Delphi 10.3 版本 26.0.33219.4899 - 已安装更新 1
我看了一下 CPU window 发现了一些奇怪的地方。
如果我使用旧式 var-block(您的版本 // A
),CPU window 会显示对 System._InitializeRecord
的调用,因为它应该如此。一切正常。
如果我使用 Default()
的内联声明(你的版本 // B
),本地记录被取消,然后使用 System._FinalizeRecord
完成,然后被取消 再次。这很奇怪而且没用,但它确实有效。
但是如果我使用你的版本 // C
,什么都没有 来初始化记录:没有 nilling out,没有 _InitializeRecord
。当我测试你的代码时,一切正常,但我可能只是幸运。
所以这显然是一个错误。请报告给 Embarcadero Quality Portal.
我猜测这是在测试默认构造函数、默认析构函数和重载赋值运算符时对编译器所做的更改的剩余部分(但随后被删除并推迟到下一个版本)。其中一些更改相当脑残(例如版本 B 中的 nilling、finalization 和 nilling),我猜其中一些更改被遗忘了。
更新
显然这已经报告给 QP:
我对 Delphi 10.3 Rio 内联变量声明感到非常兴奋。但是我 运行 遇到了 st运行ge 问题,似乎我需要在记录被内联声明后初始化它:
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 }
有例外:
Exception class $C0000005 with message 'access violation at 0x0040ac98: read of address 0xfffffff9'. Process Project8.exe (18928)
我假设从地址 -6 开始,字符串成员 sr.name 未初始化并且为 nil。
补充一下,Delphi 是新的 10.3 版本 1: Embarcadero® Delphi 10.3 版本 26.0.33219.4899 - 已安装更新 1
我看了一下 CPU window 发现了一些奇怪的地方。
如果我使用旧式 var-block(您的版本 // A
),CPU window 会显示对 System._InitializeRecord
的调用,因为它应该如此。一切正常。
如果我使用 Default()
的内联声明(你的版本 // B
),本地记录被取消,然后使用 System._FinalizeRecord
完成,然后被取消 再次。这很奇怪而且没用,但它确实有效。
但是如果我使用你的版本 // C
,什么都没有 来初始化记录:没有 nilling out,没有 _InitializeRecord
。当我测试你的代码时,一切正常,但我可能只是幸运。
所以这显然是一个错误。请报告给 Embarcadero Quality Portal.
我猜测这是在测试默认构造函数、默认析构函数和重载赋值运算符时对编译器所做的更改的剩余部分(但随后被删除并推迟到下一个版本)。其中一些更改相当脑残(例如版本 B 中的 nilling、finalization 和 nilling),我猜其中一些更改被遗忘了。
更新
显然这已经报告给 QP: