Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#18

Re: Was macht Free genau in einem Array

  Alt 9. Dez 2005, 20:33
Hi,
so musstest zwar etwas warten, aber ich habs mir jetzt noch mal anschauen können und den Fehler nun auch gefunden.
Ist eigentlich nichts weiter wildes (man kann es leicht übersehen).

Delphi-Quellcode:
  if (Index > -1) and (Index < FCount) then begin
    for i := Index to FCount - 2 do FItems[i] := FItems[i + 1];
    FItems[FCount - 1].Free;
    setlength(FItems, FCount - 1);
    FCount := length(FItems);

    if (Index = FCount) then dec(Index);
      FItemIndex := Index;
      if (Index > -1) then FActiveIndex := FItems[Index] else FActiveIndex := nil;
  end;
Guck dir mal kurz Schritt für Schritt an was du machst. Du hast ein Element an der Stelle Index, das du gerne Löschen würdest. Nun kontrollierst du ob Index gültig ist und ok, wenn es der Fall ist, werden alle Elemente die dahinter (aufpassen, nur die Referenz) nach vorne kopiert.
Danach gibst du das Element an der Stelle FCount - 1 frei. Hier liegt dein Fehler. Du kannst natürlich nicht mehr das Element an der Stelle Index freigeben, da liegt schließlich eine andere Referenz, aber das letzte Element ist auch nicht das, das du freigeben willst.
Nun ja, sagen wir deine Liste ist 5 lang und sagen wir, du hättest ein FItems wie Folgt : [1,2,3,4,5] und du löscht 2, dann bekommst du was? [1,3,4,5,5] (alles um eine Stelle nach links kopiert), dann gibst du das letzte Element frei [1,3,4,nil,nil] (weil gleiche Referenz). Wenn du nun ein Free auf nil anwenden willst knallt's.

Deshalb brauchst du einen Puffer, indem du dir das Element an der Stelle Index merkst

Delphi-Quellcode:
procedure TLaufzettel.Delete(Index: Integer);
var i : Integer;
    buffer : TDigitalerLaufzettel;
begin
  if (Index > -1) and (Index < FCount) then begin
    buffer := FItems[Index];
    for i := Index to FCount - 2 do
      FItems[i] := FItems[i + 1];
    buffer.Free;
    setlength(FItems, FCount - 1);
    FCount := length(FItems);

    if (Index = FCount) then dec(Index);
      FItemIndex := Index;
      if (Index > -1) then FActiveIndex := FItems[Index] else FActiveIndex := nil;
  end;
end;
Dann sollte alles klappen. (hoff ich jetzt mal, ungetesteter Weise)

Gruß
  Mit Zitat antworten Zitat