Einzelnen Beitrag anzeigen

Eskayp

Registriert seit: 14. Apr 2005
5 Beiträge
 
#10

Re: Memory-Leck? Verkettete Records brauchen extrem viel Ram

  Alt 15. Apr 2005, 11:43
Ok, die Explode-Routine hab ich neu geschrieben und ein wenig optimiert.
Jetzt müssen nicht mehr so viele New- und Dispose-Befehle ausgeführt werden.

Delphi-Quellcode:
// Das Aufsplitten einer Zeile anhand des SepStrings übernimmt diese Routine.
// Das Ergebnis wird in einem verketteten, temporärem Record gespeichert. So
// kann es dann später leicht in verschiedene Datenformen umgewandelt werden.
procedure MyDBExplode(pHaystack: String);
var
  i, n: Integer;
  TmpVal, NextTmpVal: PTmyTmp;
begin
  // Optimierung:
  // Da eigentlich alle Felder gleich lang sind, muss myTmpVal nicht jedesmal
  // gelöscht werden, sondern kann wiederverwendet werden. Evntl. muss dafür
  // das Feld aber dann eben mittendrin erweitert werden, oder eben am Ende
  // gestutzt.
  TmpVal := myTmpVal;

  n := 0;

  // Jetzt nach den Trennzeichen suchen und Ergebnisse im verk. Record
  // nyTmpVal speichern.
  i := Pos(mySepStr, pHaystack);
  while (i > 0) do begin
    // Diesen gefundenen Wert jetzt im verk. Record speichern
    if (myTmpVal = nil) then begin
      New(myTmpVal);
      TmpVal := myTmpVal;
      TmpVal^.next := nil;
    end
    else if (n = 0) then begin
      // nichts tun
    end
    else if (TmpVal^.next = nil) then begin
      New(TmpVal^.next);
      TmpVal := TmpVal^.next;
      TmpVal^.next := nil;
    end
    else begin
      TmpVal := TmpVal^.next;
    end;
    TmpVal^.value := Copy(pHaystack, 1, i - 1);

    // Haystack um das gefundene reduzieren und weiter suchen
    pHaystack := Copy(pHaystack, i + 1, Length(pHaystack) - i);
    i := Pos(mySepStr, pHaystack);
    Inc(n);
  end;
  // Letzten gefundenen Wert natürlich auch noch hinzufügen
  if (pHaystack <> '') then begin
    if (myTmpVal = nil) then begin
      New(myTmpVal);
      TmpVal := myTmpVal;
      TmpVal^.next := nil;
    end
    else if (n = 0) then begin
      // nichts tun
    end
    else if (TmpVal^.next = nil) then begin
      New(TmpVal^.next);
      TmpVal := TmpVal^.next;
      TmpVal^.next := nil;
    end
    else begin
      TmpVal := TmpVal^.next;
    end;
    TmpVal^.value := pHaystack;
  end;

  // Wenn es jetzt nach dem letzten gesp. Wert noch weitere Felder gibt
  // müssen diese gelöscht werden.
  if (TmpVal <> nil) then begin
    NextTmpVal := TmpVal^.next;
    TmpVal^.next := nil;
    TmpVal := NextTmpVal;
    while (TmpVal <> nil) do begin
      NextTmpVal := TmpVal^.next;
      Dispose(TmpVal);
      TmpVal := NextTmpVal;
    end;
  end;
end;
Außerdem habe ich einen ziemlich gravierenden Fehler gefunden:
Delphi-Quellcode:
  // Werte in der Zeile speichern
  TmpVal := myTmpVal;
  n := 0;
  while (TmpVal <> nil) do begin
    if (n < cnt) then begin
      curRow^.value[n] := TmpVal^.value;
      TmpVal := TmpVal^.next;
    end;
    Inc(n);
  end;
muss natürlich lauten:
Delphi-Quellcode:
  // Werte in der Zeile speichern
  TmpVal := myTmpVal;
  n := 0;
  while (TmpVal <> nil) do begin
    if (n < cnt) then
      curRow^.value[n] := TmpVal^.value;
    TmpVal := TmpVal^.next;
    Inc(n);
  end;
bzw. noch besser:
Delphi-Quellcode:
  // Werte in der Zeile speichern
  TmpVal := myTmpVal;
  n := 0;
  while ((TmpVal <> nil) and (n < cnt)) do begin
    curRow^.value[n] := TmpVal^.value;
    TmpVal := TmpVal^.next;
    Inc(n);
  end;
Die Einführung von packed records hat so gut wie gar nichts gebracht. Dafür aber die Reduzierung von Array of Shortstring auf Array of String[25]. Und zwar ganz gewaltig! Vielen Dank schonmal an Basilikum für diesen Hinweis. Jetzt muss ich noch das dyn. Array wegrationalisieren
  Mit Zitat antworten Zitat