Recent

Author Topic: Concatenate Array (of managed types)  (Read 4720 times)

soerensen3

  • Full Member
  • ***
  • Posts: 213
Concatenate Array (of managed types)
« on: September 01, 2018, 04:29:08 pm »
I'm trying to write a concatenate function for my dynamic arrays (nested in a record). The array field (FItems) is an array of a managed record. It seems to copy the array correctly but I'm not sure if this is compatible with managed types, because later in my code it frees my objects prematurely. This does only happen if I use the operator to concatenate two arrays. Is there a problem with copying the array like this or is my managed record type the problem?

Code: Pascal  [Select][+][-]
  1. class operator gP3DPlotList.+(a, b: specialize gP3DPlotList<T>): specialize gP3DPlotList < T >;
  2. var
  3.   l: Integer;
  4. begin
  5.   if ( Length( a.FItems ) = 0 ) then //FItems = array of TAutoType (my managed record)
  6.     Result:= b
  7.   else if ( Length( b.FItems ) = 0 ) then
  8.     Result:= a
  9.   else begin
  10.     Result:= default( specialize gP3DPlotList < T >);  //initialize Result
  11.     l:= Length( a.FItems ) + Length( b.FItems );
  12.     SetLength( Result.FItems, l );
  13.     Move( a.FItems[ 0 ], Result.FItems[ 0 ], Length( a.FItems ) * SizeOf( TAutoType ));
  14.     Move( b.FItems[ 0 ], Result.FItems[ Length( a.FItems )], Length( b.FItems ) * SizeOf( TAutoType ));
  15.   end;
  16. end;
  17.  
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

bytebites

  • Hero Member
  • *****
  • Posts: 640
Re: Concatenate Array (of managed types)
« Reply #1 on: September 01, 2018, 07:22:01 pm »
Move does not handle refcounting at all.

ASerge

  • Hero Member
  • *****
  • Posts: 2242
Re: Concatenate Array (of managed types)
« Reply #2 on: September 03, 2018, 01:07:06 am »
Is there a problem with copying the array like this or is my managed record type the problem?
Items that contain fields with managed types must be copied one by one. You can use System.CopyArray, but it does the same, so it's easier to copy elements one by one. Sample:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2. {$MODE OBJFPC}
  3. {$LONGSTRINGS ON}
  4.  
  5. uses SysUtils;
  6.  
  7. type
  8.   TManagedRec = record
  9.     S: string;
  10.   end;
  11.  
  12.   TManagedArray = specialize TArray<TManagedRec>;
  13.  
  14. function Concat(const List: array of TManagedArray): TManagedArray;
  15. var
  16.   iList, iArray, iResult: SizeInt;
  17.   Len: SizeInt;
  18. begin
  19.   Len := 0;
  20.   for iList := Low(List) to High(List) do
  21.     Inc(Len, Length(List[iList]));
  22.   SetLength(Result, Len);
  23.   iResult := Low(Result);
  24.   for iList := Low(List) to High(List) do
  25.     for iArray := Low(List[iList]) to High(List[iList]) do
  26.     begin
  27.       Result[iResult] := List[iList][iArray];
  28.       Inc(iResult);
  29.     end;
  30. end;
  31.  
  32. var
  33.   A1, A2, A3: TManagedArray;
  34.   R: TManagedRec;
  35. begin
  36.   SetLength(A1, 2);
  37.   A1[0].S := 'A1_0';
  38.   A1[1].S := 'A1_1';
  39.   SetLength(A2, 3);
  40.   A2[0].S := 'A2_0';
  41.   A2[1].S := 'A2_1';
  42.   A2[2].S := 'A2_2';
  43.   A3 := Concat([A1, A2, A1]);
  44.   for R in A3 do
  45.     Writeln(R.S);
  46.   Readln;
  47. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Concatenate Array (of managed types)
« Reply #3 on: September 03, 2018, 06:45:59 am »
In 3.2.0 and trunk 3.3.1 you can use either one of the Delphi modes or {$modeswitch arrayoperators+}.
Concatenation - also for managed types - is as simple as array1 + array2.
See http://wiki.lazarus.freepascal.org/User_Changes_Trunk and http://lists.freepascal.org/pipermail/fpc-pascal/2018-May/053891.html
Code: Pascal  [Select][+][-]
  1. program arrop;
  2. {$ifdef fpc}{$mode delphi}{$H+}{$endif}
  3.  
  4.  type
  5.   TManagedRec = record
  6.     S: string;
  7.   end;
  8.   TManagedArray = TArray<TmanagedRec>;
  9.  
  10. var
  11.   a:TManagedArray = [];
  12.   b:TManagedArray = [];
  13. begin
  14.   setlength(a,2);setlength(b,2);
  15.   a[0].s :='test';a[1].s :='me';
  16.   b[0].s :='hello';b[1].s :='world';
  17.   a:= a+b;
  18.   writeln(a[3].s);
  19. end.
Note mode Delphi unclutters the code. I highly recommend using it...
Note: 3.2.0 and trunk 3.3.1 also have Concat()  for dynamic arrays, including managed types.

« Last Edit: September 03, 2018, 08:36:12 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

soerensen3

  • Full Member
  • ***
  • Posts: 213
Re: Concatenate Array (of managed types)
« Reply #4 on: September 12, 2018, 10:17:49 pm »
@Thaddy: That's good to hear! Thanks for the info!

@ASerge: I still keep getting memleaks. I'm adding the elements of the array one by one now as a workaround and that solved some of them but there are probably problems somewhere else. I wish there was a more extensive explanations on how to make a managed type with refcounting and what cases have to be handled.
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

ASerge

  • Hero Member
  • *****
  • Posts: 2242
Re: Concatenate Array (of managed types)
« Reply #5 on: September 13, 2018, 04:27:18 am »
@ASerge: I still keep getting memleaks. I'm adding the elements of the array one by one now as a workaround and that solved some of them but there are probably problems somewhere else.
Detail about "somewhere else"?

soerensen3

  • Full Member
  • ***
  • Posts: 213
Re: Concatenate Array (of managed types)
« Reply #6 on: September 13, 2018, 03:14:21 pm »
I wish I could tell!  :) I try to isolate the problem to a simple project later.
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

 

TinyPortal © 2005-2018