arrays - Inicialización de Delphi Record que contiene una matriz dinámica con el operador de clase ''Implícito''
dynamic initialization (1)
Estoy tratando de averiguar si es posible inicializar un registro que contenga una matriz dinámica usando el operador de clase "implícito" en Delphi (Berlin 10.1 upd 1)
El programa adjunto produce el siguiente resultado:
ci iA r1 r2 r3
1 1 1 1 49694764491115752
2 2 2 2 11570520
3 3 3 3 0
4 4 4 4 0
5 5 5 5 0
- TRec es el tipo de registro que contiene una matriz dinámica que quiero inicializar.
- ci es una matriz constante de entero.
- ia es una matriz dinámica de números enteros.
- r1, r2, r3 son registros de tipo TRec que se inicializan de diferentes maneras.
Como puede ver en la salida, las dos primeras asignaciones (r1, r2), que usan constantes funcionan como se esperaba. La tercera asignación r3 := iArray
es aceptada por el compilador, pero el resultado está roto. El depurador muestra que el valor de v
en TRec.Implicit
ya está mal.
¿Qué está mal aquí? ¿Es esto posible?
program Project5;
{$APPTYPE CONSOLE}
{$R *.res}
type
TRec = record
iArray: array of UInt64;
class operator Implicit(const v: array of UInt64): TRec;
end;
{ TRec }
class operator TRec.Implicit(const v: array of UInt64): TRec;
var
i: integer;
begin
setlength(Result.iArray, Length(v));
for i := 0 to High(v) do
Result.iArray[i] := v[i];
end;
const
ciArray: array [0 .. 4] of UInt64 = (1, 2, 3, 4, 5);
var
i : integer;
iArray : array of UInt64;
r1, r2, r3: TRec;
begin
iArray := [1, 2, 3, 4, 5];
r1 := [1, 2, 3, 4, 5];
r2 := ciArray;
r3 := iArray;
Writeln(''ci iA r1 r1 r3'');
for I := 0 to High(ciArray) do
Writeln(ciArray[i], '' '', iArray[i], '' '', r1.iArray[i], '' '', r2.iArray[i], '' '', r3.iArray[i]);
readln;
end.
Parece que encontraste un error con el codegen allí (y también existe en el compilador Win64). Miré a través del asm generado y parece que el compilador produce una instrucción incorrecta para la sobrecarga del operador. Es por eso que los valores incorrectos terminan en la matriz dentro de la sobrecarga del operador. Por favor informe esto en Quality Portal.
Código generado por el mal resultado:
Project109.dpr.46: r3 := iArray;
0040B1F2 A1FC044100 mov eax,[$004104fc]
0040B1F7 8945E8 mov [ebp-$18],eax
0040B1FA 837DE800 cmp dword ptr [ebp-$18],$00
0040B1FE 740B jz $0040b20b
0040B200 8B45E8 mov eax,[ebp-$18]
0040B203 83E804 sub eax,$04
0040B206 8B00 mov eax,[eax]
0040B208 8945E8 mov [ebp-$18],eax
0040B20B 8D4DD8 lea ecx,[ebp-$28]
0040B20E 8B55E8 mov edx,[ebp-$18]
0040B211 4A dec edx
0040B212 B8FC044100 mov eax,$004104fc // <-- wrong one
0040B217 E87CF5FFFF call TRec.&op_Implicit
Código para un método igual:
Project109.dpr.47: r3 := TRec.Implicit(iArray);
0040B22F A1FC044100 mov eax,[$004104fc]
0040B234 8945E4 mov [ebp-$1c],eax
0040B237 837DE400 cmp dword ptr [ebp-$1c],$00
0040B23B 740B jz $0040b248
0040B23D 8B45E4 mov eax,[ebp-$1c]
0040B240 83E804 sub eax,$04
0040B243 8B00 mov eax,[eax]
0040B245 8945E4 mov [ebp-$1c],eax
0040B248 8D4DD4 lea ecx,[ebp-$2c]
0040B24B 8B55E4 mov edx,[ebp-$1c]
0040B24E 4A dec edx
0040B24F A1FC044100 mov eax,[$004104fc] // <-- correct one
0040B254 E8CFF5FFFF call TRec.Implicit
Sin embargo, puede evitar esto agregando otra sobrecarga para el operador implícito con el tipo de parámetro TArray<UInt64>
y luego también declare su variable local como ese tipo para que el compilador elija la sobrecarga correcta (para la que no genera código incorrecto en este caso).
Pero tenga en cuenta que esto solo funcionará cuando pase variables del tipo TArray<UInt64>
y llame al incorrecto cuando tenga cualquier otra array of UInt64
dinámica array of UInt64
debido a las reglas de tipo estricto de Delphis.
Actualización : Este defecto se informó en RSP-16084 y se corrigió en Delphi 10.2 Tokyo.