Следующий код генерирует исключение (c0000005 ACCESS_VIOLATION) в Delphi 10.3.1 только при компиляции в 64-разрядную версию.
Однако этот же код не генерирует исключение в Delphi 10.3.1 при компиляции в32 битаКроме того, он не дает сбоя в Delphi 10.2.3 при компиляции в 32 или 64 бита.
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.
Кажется, проблема в типе аргумента array of const
.Код по-прежнему не работает для 64 бит, если мы изменим array of const
на array of integer
, поэтому кажется, что у нового компилятора Delphi есть проблема с массивами с неизвестным числом параметров.Мы нашли способ избежать ошибки компилятора, создав тип для array of integer
, но этот прием недоступен для того, что нам нужно array of const
.
Это код ассемблера, сгенерированный для 64 битов в Delphi 10.3.1 в соответствии с 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
И это код, сгенерированный для 64 бит в Delphi 10.2.3 для той же функции:
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
Это ошибка 64-битного компилятора в Delphi 10.3.1 или мы что-то упустили?Есть ли обходные пути?