Einzelnen Beitrag anzeigen

Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#7

AW: Eintrag aus Array löschen funktioniert bei 64 bit nicht

  Alt 10. Feb 2019, 10:58
Ich vermute, er möchte noch eine trailing 0 mitschleppen. Das war vielleicht mal sinnvoll......
Das kann nicht mal zu Zeiten von string = string[255] funktioniert haben. Ein TArray<string> ist immer ein Array von Pointern und Sizeof(string) ist immer 4 (32 Bit) oder 8 (64 Bit). Das 1 Byte mehr macht hier definitiv nur Ärger. Es sorgt nämlich dafür, daß der letzte Array-Eintrag verfälscht wird.

Ich wäre in diesem Fall aber sowieso vorsichtig, was die Referenzzählung bei Strings betrifft. Die kann mit dem Move schon mal gehörig durcheinander geraten. Selbst bei korrektem Count zeigen nach dem Move die letzten beiden Array-Elemente auf denselben String. Ich glaube kaum, daß bei dem Move auch die Referenzzählung entsprechend angepasst wird. Beim folgenden SetLength allerdings schon. Dieses Beispielprogramm verdeutlicht die Problematik und zeigt, daß die Verwendung von Delete nicht nur einfacher, sondern auch sicherer ist.


Delphi-Quellcode:
program Project490;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

function StringRefCount(const Value: string): Integer;
var
  P: PInteger;
begin
  P := @Value[1];
  Dec(P, 2);
  Result := P^;
end;

procedure Main;
var
  arr: TArray<string>;
  I: Integer;
begin
  SetLength(arr, 10);
  for I := 0 to 8 do begin
    arr[I] := I.ToString;
  end;
  arr[9] := arr[8];

  Writeln('Verwendung von Move und SetLength');
  Writeln('8 und 9 zeigen auf denselben string, RefCount ist OK');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  Writeln('9: ', StringRefCount(arr[9]));
  Move(arr[1], arr[0], 9*SizeOf(arr[0]));
  Writeln('nach Move: 7,8 und 9 zeigen auf denselben string, aber RefCount is 2!');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  Writeln('9: ', StringRefCount(arr[9]));
  SetLength(arr, 9);
  Writeln('nach SetLength: RefCount für 9 wird runtergezählt.');
  Writeln('7 und 8 zeigen auf denselben string, aber RefCount ist 1!');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  arr[8] := '';
  Writeln('8 ist jetzt leer, RefCount wurde erniedrigt.');
  Writeln('7 zeigt immer noch auf diesen string, aber RefCount ist 0!');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  Writeln;
end;

procedure Main2;
var
  arr: TArray<string>;
  I: Integer;
begin
  SetLength(arr, 10);
  for I := 0 to 8 do begin
    arr[I] := I.ToString;
  end;
  arr[9] := arr[8];

  Writeln('Verwendung von Delete');
  Writeln('8 und 9 zeigen auf denselben string, RefCount ist OK');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  Writeln('9: ', StringRefCount(arr[9]));
  Delete(arr, 0, 1);
  Writeln('nach Delete: RefCount für 9 wird runtergezählt.');
  Writeln('7 und 8 zeigen auf denselben string, RefCount ist OK');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  arr[8] := '';
  Writeln('8 ist jetzt leer, RefCount wurde erniedrigt.');
  Writeln('7 zeigt immer noch auf diesen string, RefCount ist OK');
  Writeln('7: ', StringRefCount(arr[7]));
  Writeln('8: ', StringRefCount(arr[8]));
  Writeln;
end;

begin
  try
    Main;
    Main2;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat