AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

Ein Thema von DelphiBandit · begonnen am 13. Nov 2014 · letzter Beitrag vom 20. Nov 2014
Antwort Antwort
Seite 2 von 3     12 3   
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#11

AW: MemoryLeak (FastMM4) nach Befüllen einer Klasse aus JSON-String

  Alt 19. Nov 2014, 10:43
<noch nicht ganz korrekte Fehlerbeschreibung> (daher beitrag gelöscht)
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.

Geändert von stoxx (19. Nov 2014 um 10:49 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

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

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 19. Nov 2014, 12:00
Das hat wohl keine Relevanz, aber das Property SecondClassEntries verweist auf das falsche Feld.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von DelphiBandit
DelphiBandit

Registriert seit: 19. Feb 2007
Ort: bei Walsrode
165 Beiträge
 
Delphi 10.4 Sydney
 
#13

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 19. Nov 2014, 12:09
Danke für den Hinweis Uwe. Das habe ich durch Blick in die json-Datei auch schon bemerkt und in der "aktuellen" Version des kleinen Testprogramms korrigiert.

Habe auch die bisherigen Info's von stoxx mit eingearbeitet (2 x FEntryList). Der abstrakte Error ist jetzt weg, aber das Speicherleck bleibt nach wie vor erhalten, weil die destructor-Routinen der untergeordneten Objekte beim .Free des aus json erzeugten Objektes nicht aufgerufen werden. Nach Erzeugung durch den überladenen Konstruktor wird jetzt zwar TEntryList.destroy ohne abstrakten Fehler aufgerufen, die enthaltene Liste FEntryLists ist aber (bereits?) nil.

Werde das Archiv mal eben aktualisieren. Schade geht nicht, kann den ersten Beitrag nicht mehr bearbeiten Also dann hier dran.
Angehängte Dateien
Dateityp: zip SimpleJSONLeak.zip (23,3 KB, 8x aufgerufen)
Carsten

Geändert von DelphiBandit (19. Nov 2014 um 13:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#14

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 19. Nov 2014, 14:18
also nun nochmal komplett.

im Anhang eine Version ohne Speicherleck.
Zum einen ist zu beachten, dass eine Objectlist keine TCollection ist, also die Elemente der Liste müssen manuell selbst im Destructor gelöscht werden.
Delphi hat aber ein Bug in "DeleteRange" in TList<> und TObjectList<>, welcher den Abstrakten Fehler erzeugt.
Umgehen kann man ihn, indem man jedes Element einzeln im Destructor löscht. (absteigend durchgehen)
Erzeugung über JSON jetzt besser über eine class function.

Im Anhang ein funktionierendes Projekt (ohne Speicherlecks)

Delphi-Quellcode:
destructor TObjectsTEntry.destroy;
var i : Integer;
    entry : TEntry;
begin
  for i := self.Count-1 downto 0 do begin
    entry := self.Items[i];
    entry.Free;
    self.Delete(i);
  end;
  self.Clear;
  inherited;
end;

Delphi-Quellcode:
class function TEntryList.Create(aJSON: string) : TEntryList;
begin
  result := TJson.JsonToObject<TEntryList>(aJSON);
end;
Angehängte Dateien
Dateityp: rar SimpleJSONLeak.rar (6,0 KB, 11x aufgerufen)
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
Benutzerbild von DelphiBandit
DelphiBandit

Registriert seit: 19. Feb 2007
Ort: bei Walsrode
165 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 19. Nov 2014, 15:47
Hallo,

vielen Dank für Eure Mühe und stoxx für das Projekt ohne Speicherleck! Ich bin bis eben gerade noch davon ausgegangen, dass TObjectList<TIrgendwas> beim Erzeugen genauso OwnsObjects als Default auf True hat und sich beim .Free der ObjectList damit auch die Listenelemente selbst freigeben?

Bei allen anderen Objektkonstrukten, die bei mir kein Json nutzen, funktioniert das mit dieser Automatik auch bisher wunderbar und ohne Speicherverluste. Siehe in meiner Demo z.B. beim Populate-Button, lokale entryList wird am Ende freigegeben und erzeugt kein MemLeak. Kommentiere ich das am Ende gibt es ein MemLeak.

Oder taucht der von Dir angesprochene Bug nur auf, wenn man zusätzlich Json nutzt und muss man sich deshalb selbst um die Freigabe kümmern?

also nun nochmal komplett.

im Anhang eine Version ohne Speicherleck.
Zum einen ist zu beachten, dass eine Objectlist keine TCollection ist, also die Elemente der Liste müssen manuell selbst im Destructor gelöscht werden.
Delphi hat aber ein Bug in "DeleteRange" in TList<> und TObjectList<>, welcher den Abstrakten Fehler erzeugt.
Umgehen kann man ihn, indem man jedes Element einzeln im Destructor löscht. (absteigend durchgehen)
Carsten

Geändert von DelphiBandit (19. Nov 2014 um 17:55 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#16

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 19. Nov 2014, 21:55
Hallo,

vielen Dank für Eure Mühe und stoxx für das Projekt ohne Speicherleck! Ich bin bis eben gerade noch davon ausgegangen, dass TObjectList<TIrgendwas> beim Erzeugen genauso OwnsObjects als Default auf True hat und sich beim .Free der ObjectList damit auch die Listenelemente selbst freigeben?
also ich hab in den Quelltexten in den Generic Units nichts im Destructor finden können.
Ich bin aber sowieso eher klassisch unterwegs und geb alles, was ich erzeugt habe, auch wieder frei.
Gleich nach dem Schreiben vom Constructor fülle ich ebenso den Destructor.
Bei Klassen mit Treestrukturen würde die Automatik sicher gut funktionieren, aber nicht immer sind ja Objekte gleich Owner, nur weil irgendwo ein Link drauf ist, da muss man eh selber freigeben.
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

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

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 20. Nov 2014, 01:29
Zwei Dinge konnte ich feststellen:

1. Der abstrakte Fehler kommt, weil der arrayManager mit im JSON-String steht. Dadurch wird beim Konvertieren in das Objekt eine TArrayManager instantiiert, obwohl dies nur die abstrakte Klasse ist.

2. Das inherited in TObjectsEntries.create und TObjectsTEntry.create ruft TList<T>.Create auf und nicht TObjectList<T>.Create . Dadurch wird OwnsObjects nicht gesetzt und man muss die Items im Destroy selbst wegräumen. Ersetzt man das inherited durch inherited Create funktioniert es.

Den abstrakten Fehler bekommt man nicht ganz so einfach weg. Eigentlich müsste das in System.Generics.Collections durch ein entsprechendes Attribut geregelt werden. Alternativ kann man das TJson.ObjectToJsonString wegschmeißen und den Spaß von Hand nachbilden. Würde TJson.ObjectToJsonObject in der ersten Zeile statt TJSONMarshal.Create(TJSONConverter.Create) besser TJSONConverters.GetJSONMarshaler aufrufen, könnte man ja noch was mit den MarshalFlags machen - ist leider nicht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von DelphiBandit
DelphiBandit

Registriert seit: 19. Feb 2007
Ort: bei Walsrode
165 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 20. Nov 2014, 07:50
Ich denke ich werde auch dazu übergehen mich um alles selbst zu kümmern. Da will man einmal Verantwortung abgeben Automatismus hin und her, man sieht, was man davon hat sich auf diesen zu verlassen. Werde alles auf TList<..> umstellen, sauber hinter mir aufräumen und fertig ist.

Nichts desto trotz sehe ich das hier beschriebene Problem im Endeffekt als Bug und habe es für die zukünftige Version XEx++ mal in der qc gemeldet. Auch wenn wir nicht jeden Update-Zyklus mitnehmen, vielleicht wird es irgendwann gefixt werden. Das meines Erachtens Blöde daran ist, dass man es gar nicht so offensichtlich mitbekommt. Solange man nicht gezielt nach Speicherlecks sucht, was man immer mal wieder tun sollte

Die Stelle der Freigabe in einer ObjectList ist imho nicht der destructor, sondern die Nachricht, dass ein Objekt aufgelöst wurde
Delphi-Quellcode:
procedure TObjectList<T>.Notify(const Value: T; Action: TCollectionNotification);
begin
  inherited;
  if OwnsObjects and (Action = cnRemoved) then
    Value.DisposeOf;
end;
also ich hab in den Quelltexten in den Generic Units nichts im Destructor finden können.
Ich bin aber sowieso eher klassisch unterwegs und geb alles, was ich erzeugt habe, auch wieder frei.
Gleich nach dem Schreiben vom Constructor fülle ich ebenso den Destructor.
Auf jeden Fall nochmal vielen Dank für Eurer aller Hilfe
Carsten

Geändert von DelphiBandit (20. Nov 2014 um 07:56 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

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

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 20. Nov 2014, 09:19
Um das nochmal deutlich zu machen: Das Problem taucht bei der Kombination von TJON und TList<T> auf. Die aktuelle Implementierung des JSON-Marshaling stellt bestimmte Anforderungen an die zu konvertierenden Klassen, die von TList<T> (noch) nicht erfüllt werden.

Es ist halt schon immer so gewesen, daß die einfachen Lösungen nur für einen Teil der Anwendungsfälle funktionieren. Für die übrigen muss man dann wieder selbst Hand anlegen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.093 Beiträge
 
Delphi 10 Seattle Enterprise
 
#20

AW: JSON-Serialisierung von generischen Listen nur mit MemoryLeaks (FastMM4)

  Alt 20. Nov 2014, 10:03
Nichts desto trotz sehe ich das hier beschriebene Problem im Endeffekt als Bug und habe es für die zukünftige Version XEx++ mal in der qc gemeldet.
Link bitte
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:49 Uhr.
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