Delphi 10.3.1 compiler generates code that issues an exception when compiled to 64 bits

Pep*_*Pep 10 delphi delphi-10.3-rio

The following code generates an exception (c0000005 ACCESS_VIOLATION) in Delphi 10.3.1 only when compiled to 64-bit.

However, the same code does not generate an exception in Delphi 10.3.1 when compiled to 32 bits. Also, it does not fail in Delphi 10.2.3 when compiled to either 32 bits or 64 bits.

program CrashOn64;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TMyBaseClass = class
  protected
    procedure Setup(aParams: array of const); virtual;
  public
  end;

type
  TMyWorkClass = class(TMyBaseClass)
  protected
    procedure DoSetup; virtual;
  public
    procedure Setup(aParams: array of const); override;
  end;

{ TMyBaseClass }

procedure TMyBaseClass.Setup(aParams: array of const);
begin
end;

{ TMyWorkClass }

procedure TMyWorkClass.DoSetup;
begin
  inherited;   
end;

procedure TMyWorkClass.Setup(aParams: array of const);
begin
  inherited;
  DoSetup
end;

// main

var
  myClass: TMyWorkClass;
begin
  try
    myClass:=TMyWorkClass.Create;
    try
      myClass.Setup([123]); // <-- Crash on Windows 64-bit
      writeln('OK!')
    finally
      myClass.Free
    end
  except
    on E: Exception do Writeln(E.ClassName, ': ', E.Message);
  end;

  readln; // Wait for Enter key
end.
Run Code Online (Sandbox Code Playgroud)

The issue seems to be in the argument type being array of const. The code still fails for 64 bits if we change array of constto array of integer, so it seems that the new Delphi compiler has an issue with arrays with an unknown number of parameters. We found the trick to avoid the compiler bug by creating a type for array of integer but this trick is not available for what we need array of const.

This is the assembler code generated for 64 bits in Delphi 10.3.1 accoding to the CPU View:

CrashOn64.dpr.41: inherited;
0000000000428888 488B7528         mov rsi,[rbp+$28]
000000000042888C 488D7D20         lea rdi,[rbp+$20]
0000000000428890 48B9FFFFFFFFFFFFFF1F mov rcx,$1fffffffffffffff <<< What????????
000000000042889A F348A5           rep movsq                     <<< Crashes here.
000000000042889D A5               movsd
000000000042889E 66A5             movsw
00000000004288A0 A4               movsb
00000000004288A1 488B4D50         mov rcx,[rbp+$50]
00000000004288A5 488D5520         lea rdx,[rbp+$20]
00000000004288A9 448B4560         mov r8d,[rbp+$60]
00000000004288AD E8CEFEFFFF       call TMyBaseClass.Setup
Run Code Online (Sandbox Code Playgroud)

这是在Delphi 10.2.3中针对相同功能为64位生成的代码:

CrashOn64.dpr.41: inherited;
0000000000427329 488B4D50         mov rcx,[rbp+$50]
000000000042732D 488B5528         mov rdx,[rbp+$28]
0000000000427331 448B4560         mov r8d,[rbp+$60]
0000000000427335 E8E6FEFFFF       call TMyBaseClass.Setup
Run Code Online (Sandbox Code Playgroud)

这是Delphi 10.3.1中的64位编译器错误,还是我们缺少任何内容?有什么解决方法吗?

LU *_* RD 14

这是错误,应报告1。正如问题中提到的,它对于每种类型的open array都失败。

解决方法是const在方法中将数组定义为:

procedure Setup(const aParams: array of const); 
Run Code Online (Sandbox Code Playgroud)

将open数组声明为const,通过引用传递该数组,而没有const时,它将按值作为副本传递。在这种情况下,Rio版本将失败。


1据报告为:在Rio中使用开放数组参数调用继承函数时发生访问冲突