我对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,则代码可以正常工作
但是如果我在行上声明sr
// C然后在// D行崩溃,分别在26222行的system.pas中崩溃:
MOV ECX,[EDX-skew].StrRec.refCnt { fetch refCnt }
例外:
异常类$ C0000005,消息为“访问冲突位于 0x0040ac98:读取地址0xfffffff9'。处理Project8.exe(18928)
我将从地址-6假设,字符串成员sr.name未初始化且为nil。
为了完整起见,Delphi是新的10.3版本1: Embarcadero®Delphi 10.3版本26.0.33219.4899-已安装更新1
答案 0 :(得分:6)
我在CPU窗口中查看了一下,发现了一些奇怪的地方。
如果我使用旧式var块(您的版本// A
),则CPU窗口将显示对System._InitializeRecord
的调用,如其应有的那样。一切正常。
如果我将内联声明与Default()
(您的版本// B
)一起使用,则会删除本地记录,然后使用System._FinalizeRecord
进行最终确定,然后再次删除 强>。那是很奇怪和没用的,但是可以。
但是,如果我使用的是您的版本// C
,则不执行任何操作来初始化记录:不删节,不_InitializeRecord
。当我测试您的代码时,事情确实起作用了,但是我可能很幸运。
所以这显然是一个错误。请报告给Embarcadero Quality Portal。
我猜测,这是在测试默认构造函数,默认析构函数和重载的赋值运算符(但随后将其删除并推迟到下一个版本)时对编译器所做的其余更改。其中一些变化相当死脑筋(例如B版本中的nilling,finalization和nilling),我想其中一些变化被遗忘了。
很明显,这已经报告给QP: