Delphi 10.3 Rio-是否需要初始化内联声明的记录变量? [英] Delphi 10.3 Rio - Is initializaiton of inline declared record variables needed?

查看:209
本文介绍了Delphi 10.3 Rio-是否需要初始化内联声明的记录变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am quite excited about Delphi 10.3 Rio inline variable declarations. However I ran into strange problem and it seems that I need to initialize record after it has been inline declared:

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,代码可以正常工作:

The code works fine if I declare sr on line:


  • // A(旧样式声明)或在线

  • // B(带有初始化的内联声明)。

但是如果我在线声明sr

However if I declare sr on line


  • // C然后在// D行崩溃,分别在system.pas的26222行:

  • //C then it crashes on line //D, respective in system.pas on line 26222:

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


,但以下情况除外:


异常类$ C0000005,消息为
访问冲突0x0040ac98:读取地址0xfffffff9'。处理Project8.exe(18928)

Exception class $C0000005 with message 'access violation at 0x0040ac98: read of address 0xfffffff9'. Process Project8.exe (18928)

我假设从地址-6开始,字符串成员sr.name未初始化,并且

I would assume from the address -6, that the string member sr.name is not initialized and is nil.

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

Just to be complete, Delphi is the new 10.3 release 1: Embarcadero® Delphi 10.3 Version 26.0.33219.4899 - Installed Update 1

推荐答案

我在CPU窗口中查看了一下,发现了一些奇怪的地方。

I took a look in the CPU window and found a few oddities.

如果我使用旧式var块(您的版本 // A ),则CPU窗口将显示对 System._InitializeRecord的调用,应该这样。一切正常。

If I use the old-style var-block (your version // A), the CPU window shows a call to System._InitializeRecord, as it should. All is fine and normal.

如果我将内联声明与 Default()(您的版本 // B ),将本地记录清除掉,然后使用 System._FinalizeRecord 完成,然后再次清除 / strong>。

If I use the inline declaration with Default() (your version // B), the local record is nilled out, then finalized using System._FinalizeRecord and then nilled out again. That is pretty weird and useless, but it works.

但是如果我使用您的版本 // C 没有任何操作来初始化记录:没有剪裁,没有 _InitializeRecord 。当我测试您的代码时,事情确实起作用了,但我可能很幸运。

But if I use your version // C, nothing is done to initialize the record: no nilling out, no _InitializeRecord. When I tested your code, things did work, but I was probably just lucky.

因此,这显然是一个错误。请报告给 Embarcadero质量门户网站

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

I guess this is a remainder of the changes made to the compiler when default constructors, default destructors and overloaded assignment operators were tested (but then removed and postponed to a next release). Some of these changes were rather braindead (like the nilling, finalization and nilling again, as in version B), and I guess some of these changes were forgotten.

很明显,这已经报告给QP:

Obviously this was already reported to QP:

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

这篇关于Delphi 10.3 Rio-是否需要初始化内联声明的记录变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆