arrays delphi dynamic initialization record

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.