![]() |
Peinliche Frage zu generischen Listen
Ich sehe gerade den Wald vor lauter Bäumen nicht, und komme nicht mehr voran. Ich schildere mal was ich erreichen wollte, und dann zeige ich was ich getan habe, und was damit passiert :(
Ich habe viele Messwerte (es geht im Prinzip immer noch um das ![]() Hier das wesentliche zu den Klassen:
Delphi-Quellcode:
Hier die Implementierung. Kleiner Hinweis zum Konstruktor eines TDevValue: Es wird ein String erwartet, der eine Zeile einer csv-Datei repräsentiert.
// Es gibt noch einen Stapel weitere Werte in dieser Klasse, die allesamt single sind,
// damit tragen sie nicht mehr zum Problem bei, als die hier noch aufgeführten Werte TDevValue = class private fTimeOffset: single; fQUALITY1: string; fQUALITY2: string; fQUALITY3: string; fMQUALITY: string; fTime : TDateTime; fMOVEMENT: Boolean; procedure Init; public property TimeOffset: single read fTimeOffset; property QUALITY1: string read fQUALITY1; property QUALITY2: string read fQUALITY2; property QUALITY3: string read fQUALITY3; property MQUALITY: string read fMQUALITY; property Time : TDateTime read fTime; property MOVEMENT: Boolean read fMOVEMENT; constructor Create(aRow: string; aFS: TFormatSettings); destructor Destroy; override; end; TValueList = class private fLastTimeStamp: single; fDevValueList : TList<TDevValue>; fs : TFormatSettings; function GetItemCount: Integer; public function Add(aRow: string): Integer; function Get(aIndex: Integer): TDevValue; property Count: Integer read GetItemCount; constructor Create; destructor Destroy; override; end;
Delphi-Quellcode:
Irgendwie ist das alles trivial einfach...aber FastMM schimpft ganz dolle mit mir, daß ich praktisch keines der vielen tausend TDevValue Objekte freigegeben habe. Was habe ich falsch gemacht?
constructor TDevValue.Create(aRow: string; aFS: TFormatSettings);
var myRow: TStringList; begin inherited Create; Self.Init; if aRow.Length > 20 then begin myRow := TStringList.Create; try myRow.Delimiter := ';'; myRow.StrictDelimiter := True; myRow.DelimitedText := aRow; fTimeOffset := StrToFloatDef(myRow[keyTimeOffset], 0, aFS); fQUALITY1 := myRow[keyQUALITY1]; fQUALITY2 := myRow[keyQUALITY2]; fQUALITY3 := myRow[keyQUALITY3]; fMQUALITY := myRow[keyMQUALITY]; fTime := UnixToDateTime(Floor(StrToFloatDef(myRow[keyTime], 0, aFS)), False); fMOVEMENT := myRow[keyMOVEMENT] = '1'; finally myRow.Free; end; end; end; destructor TDevValue.Destroy; begin // Der vermutlich klägliche Versuch UniCodeString Memoryleaks zu beseitigen fQUALITY1 := ''; fQUALITY2 := ''; fQUALITY3 := ''; fMQUALITY := ''; inherited; end; procedure TDevValue.Init; begin fTimeOffset := -1; fQUALITY1 := ''; fQUALITY2 := ''; fQUALITY3 := ''; fMQUALITY := ''; fTime := NaN; fMOVEMENT := False; end; /////// Jetzt die Liste ////// function TValueList.Add(aRow: string): Integer; var found : Boolean; i : Integer; myDevValue: TDevValue; begin found := False; i := 0; myDevValue := TDevValue.Create(aRow, fs); if fDevValueList.Count > 0 then begin repeat if myDevValue.TimeOffset = fDevValueList[i].TimeOffset then found := True else Inc(i); until found or (i > fDevValueList.Count - 1); end; if not found then begin Result := fDevValueList.Add(myDevValue); if myDevValue.TimeOffset > fLastTimeStamp then fLastTimeStamp := myDevValue.TimeOffset; end else begin // Was ich nich brauche, kann gleich wieder weg myDevValue.Free; Result := i; end; end; constructor TValueList.Create; begin fDevValueList := TList<TDevValue>.Create; // Die csv-Datei liefert numerische Werte mit Punkt als Dezimaltrenner fs := TFormatSettings.Create; fs.DecimalSeparator := '.'; fLastTimeStamp := 0; end; destructor TValueList.Destroy; begin // Was ist hier zu tun, um wirklich die einzelnen Listenelemente freizugeben? fDevValueList.DeleteRange(0, fDevValueList.Count - 1); fDevValueList.Free; inherited; end; function TValueList.Get(aIndex: Integer): TDevValue; begin if (aIndex >= 0) and (aIndex < fDevValueList.Count) then Result := fDevValueList[aIndex] else Result := nil; end; function TValueList.GetItemCount: Integer; begin Result := fDevValueList.Count; end; Sherlock |
AW: Peinliche Frage zu generischen Listen
kenn mich mit genereischen listen nicht aus (hab die noch nicht)aber musst du da die Clear procedure der TList nicht überschreiben und die Dinger dann Freen die in der Liste sind?
|
AW: Peinliche Frage zu generischen Listen
bei Fragen die dir peinlich sind, hilft es ab und zu in die Hilfe zu schauen:
![]() Zitat:
|
AW: Peinliche Frage zu generischen Listen
Moin... :P
Ohne alles gelesen zu haben... :P TList<> nach TObjectList<> ... schaust zu hier: ![]() OwnsObjects = True |
AW: Peinliche Frage zu generischen Listen
Ich glaube bei TList musst du dich selbst darum kümmern die Objekte in der Liste freizugeben.
Also beim Destory alle Items durchgehen und diese freigeben. Mit TObjectList kannst du die Eigenschaft "OwnsObject" setzen. Damit kümmert sich die Liste selbst darum die Items freizugeben beim Aufruf von .Free. Zu langsam :D |
AW: Peinliche Frage zu generischen Listen
Menno, keine rote Box. So einfach geht das...
Mache mich gleich dran. Danke! Sherlock |
AW: Peinliche Frage zu generischen Listen
Es wurde ja schon mehrfach erwähnt. Die TList Klasse gibt die Elemente die sie beinhaltet nicht wieder automatisch frei. Siehe auch
![]() Alternativ müsstest du im Destructor deiner TValueList Klasse durch alle Elemente iterieren und diese dann freigeben. Übrigens:
Delphi-Quellcode:
Kann man auch so schreiben:
if fDevValueList.Count > 0 then
begin repeat if myDevValue.TimeOffset = fDevValueList[i].TimeOffset then found := True else Inc(i); until found or (i > fDevValueList.Count - 1); end;
Delphi-Quellcode:
Mir stellt sich jetzt nur noch die Frage, wieso du überhaupt noch die Liste durchlaufen musst. Du setzt dir doch schon in
if fDevValueList.Count > 0 then
begin repeat if myDevValue.TimeOffset = fDevValueList[i].TimeOffset then found := True else Inc(i); until found or (i = fDevValueList.Count); // <-------- ÄNDERUNG HIER end;
Delphi-Quellcode:
den zuletzt hinzugefügten TimeStamp. Reicht es dann nicht einfach zu überprüfen, ob der neue TimeStamp größer/neuer ist als der zuletzt hinzugefügte?
fLastTimeStamp
|
AW: Peinliche Frage zu generischen Listen
Ja, schon sind die Objekte alle freigegeben worden, und ich kann mich dem Freigeben der Bitmaps widmen.... Danke Euch allen!
Und Aviator, danke für die Optimierung...ich stand wohl sehr weit neben mir. Im Nachbarort, sozusagen :D Sherlock |
AW: Peinliche Frage zu generischen Listen
Zitat:
Hast du denn noch meine zusätzliche Anmerkung gelesen? Kannst du dich auf den TimeStamp verlassen den du dir zwischenspeicherst? |
AW: Peinliche Frage zu generischen Listen
Das IF könnte man och noch wegoptimieren, wenn man die Schleife zuerst prüft.
Delphi-Quellcode:
Aber wichtiger wären die Float-Vergleiche, denn die Floats haben ja dieses winzige Rundungsproblemchen.
while i < fDevValueList.Count do begin
//if myDevValue.TimeOffset = fDevValueList[i].TimeOffset then begin if SameValue(myDevValue.TimeOffset, fDevValueList[i].TimeOffset) then begin found := True; Break; end; Inc(i); end; ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz