Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Move und FillChar bei strings. (https://www.delphipraxis.net/180684-move-und-fillchar-bei-strings.html)

Bjoerk 8. Jun 2014 08:56

Delphi-Version: 2007

Move und FillChar bei strings.
 
Ich hab manche Routinen die Geschwindigkeitsoptimiert sind und verwende da deshalb (gelegentlich) eigene Stringlisten (FItems: array of string). Jetzt wollte ich mal fragen ob die Moves und FillChars so richtig sind und ob der Compiler was mit SizeOf(string) anfangen kann? :gruebel:
Delphi-Quellcode:
procedure TMyStringList.Insert(const Index: integer; const Value: string);
var
  N: integer;
begin
  SetCount(FCount + 1);
  if Index < FCount - 1 then
  begin
    N:= (FCount - 1 - Index) * SizeOf(string);
    Move(FItems[Index], FItems[Index + 1], N);
    FillChar(FItems[Index], SizeOf(string), 0);
  end;
  FItems[Index] := Value;
end;

procedure TMyStringList.Delete(const Index: integer);
var
  N: integer;
begin
  if Index < FCount - 1 then
  begin
    N:= (FCount - 1 - Index) * SizeOf(string);
    Move(FItems[Index + 1], FItems[Index], N);
    FillChar(FItems[FCount - 1], SizeOf(string), 0);
  end;
  SetCount(FCount - 1);
end;

DeddyH 8. Jun 2014 09:29

AW: Move und FillChar bei strings.
 
Lass Dir doch einfach mal den Wert von SizeOf(string) ausgeben, da dürfte 4 bzw. 8 bei herauskommen, da es sich intern ja um einen Pointer handelt.

Bjoerk 8. Jun 2014 09:47

AW: Move und FillChar bei strings.
 
Ja, bei mir (Ansi) kommt immer 4 raus, ejal wie lang der string ist?
BTW, bei Delete bekomme ich ein Speicherloch!?

DeddyH 8. Jun 2014 09:52

AW: Move und FillChar bei strings.
 
Ja eben, es ist unter 32 Bit immer 4 (Pointergröße). Um die Größe in Bytes zu ermitteln, müsstest Du die Länge mit SizeOf(char) multipilizieren.

Bjoerk 8. Jun 2014 10:47

AW: Move und FillChar bei strings.
 
Du meinst bei Fillchar? OK, hab ich geändert. Speicherloch bleibt aber?

Delphi-Quellcode:
  FillChar(FItems[..], Length(FItems[..]) * SizeOf(char), 0);

nuclearping 8. Jun 2014 14:38

AW: Move und FillChar bei strings.
 
Delphi-Quellcode:
Finalize(FItems[...]);
bzw.
Delphi-Quellcode:
Finalize(FItems);
?

Bjoerk 8. Jun 2014 15:42

AW: Move und FillChar bei strings.
 
Nee. Leider. Hatte auch schon SetLength(FItems[], 0) probiert. Macht es nicht. Das Move scheint wohl so auch nicht zu gehen selbst wenn ich die Puffergröße in Bytes genau ausrechne?

TiGü 8. Jun 2014 17:45

AW: Move und FillChar bei strings.
 
Siehe hier:
http://www.delphipraxis.net/1255938-post2.html

Also anstatt
Delphi-Quellcode:
FillChar(FItems[Index], SizeOf(string), 0);
lieber mal
Delphi-Quellcode:
FItems[Index] := '';
.

Bjoerk 8. Jun 2014 18:04

AW: Move und FillChar bei strings.
 
Ok. aber was ist dann mit dem Referenzzähler?

Ich bin mit wegen den strings nicht sicher und bezweifele langsam ob das so geht und ob’s überhaupt an dem Finalize liegt? Mir scheint man kann auch bei strings nicht so moven? Bei Shortstring funktionierst hingegen einwandfrei?

Ich poste mal die Klasse:

Delphi-Quellcode:
destructor TMyStringList.Destroy;
begin
  Clear;
  inherited Destroy;
end;

procedure TMyStringList.Clear;
begin
  FCount := 0;
  Capacity := 0;
end;

function TMyStringList.DeltaCapacity: integer;
begin
  if FCapacity > 64 then
    Result := FCapacity div 4
  else
    if FCapacity > 8 then
      Result := 16
    else
      Result := 4;
end;

function TMyStringList.Add(const Value: string): integer;
begin
  Result := FCount;
  Insert(Result, Value);
end;

procedure TMyStringList.Insert(const Index: integer; const Value: string);
begin
  if FCount = FCapacity then
    Capacity := FCapacity + DeltaCapacity; // property Capacity: integer write SetCapacity;
  if Index < FCount then
  begin
    Move(FItems[Index], FItems[Index + 1], (FCount - Index) * SizeOf(string));
    Finalize(FItems[Index]);
  end;
  FItems[Index] := Value;
  Inc(FCount);
end;

procedure TMyStringList.Delete(const Index: integer);
begin
  Dec(FCount);
  if Index < FCount then
  begin
    Move(FItems[Index + 1], FItems[Index], (FCount - Index) * SizeOf(string));
    Finalize(FItems[FCount]);
  end;
  FItems[FCount] := '';
end;

function TMyStringList.GetItems(Index: integer): string;
begin
  Result := FItems[Index];
end;

procedure TMyStringList.SetItems(Index: integer; const Value: string);
begin
  FItems[Index] := Value;
end;

procedure TMyStringList.SetCapacity(const Value: integer);
begin
  FCapacity := Value;
  SetLength(FItems, FCapacity);
end;

himitsu 8. Jun 2014 18:55

AW: Move und FillChar bei strings.
 
PS: Wenn man probemlos PChars kopieren will, warum verwendet man nicht darür die entsprechenden APIs, welche für PChars vorgesehen sind? :roll:
Diese zählen die Länge in Chars, was dann überall stimmt., egal ob Unicode oder nicht, ohne daß man auf die Größe der Chars achten muß.

StrMove, StrLMove, StrECopy, StrLCopy, StrPCopy, ... (siehe SysUtils)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:17 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz