Следующий код создает исключение (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 или мы что-то упустили? Есть ли обходные пути?
Integer
. Это работает? - person David Heffernan   schedule 15.04.2019array of const
фактическиarray of TVarRec
- возможно, что-то изменилось в 10.3.1 с вариантными записями? Что, если вы явно передадите действительныйTVarRec
вместо неявного[123]
? - person J...   schedule 15.04.2019