Ich habe irgendwie eine Wissenslücke oder denke falsch.
Leider hilft auch nicht "RTFM"
Bisher nahm ich an, daß Objekte, die ich in einer Methode create auch brav wieder freigebe (zB TStringList).
Bei Beispielen mit TJSONObject scheint aber manches anders zu laufen - was mich sehr verwirrt und der Code bei Ausführung entweder knallt oder Windows mein Programm freundlicherweise ohne jeden Hinweis einfach beendet, nachdem es zuvor Fehlermeldungen an überraschenden Stellen ausgibt, die bislang sehr gut funktioniert haben (also MemoryLeak bei Verwendung von TJSONObject?)..
Ich habe also ein Programm anhand von Beispielen zusammengebaut, das lief bislang eigentlich gut, dann fiel mir das Leak auf und ich begann damit, alles mit create geschaffene auch wieder mit free zu entfernen.
Sollte ich besser destroy anstelle von free verwenden?
Die Hilfe sagt "Mit Destroy geben Sie die TJSONObject-Instanz frei." - Aha, wozu gibt es dann auch Free? Es knallt aber in beiden Fällen.
Leider strotzt die Hilfe nur so mit nicht vorhandenen Anwendungsbeispielen.
Und die Beispiele im Internet verzichten häufig auf die Freigabe oder realisieren sie mit .free - und tatsächlich, an manchen Stellen in meinem Code funktioniert die Freigabe von TJSONObject auch mit .free ohne zum knallen
Nundenn, ich baue einen Request zusammen und sende ihn dann an ein Gerät - hier nur der Code als Beispiel bzw. wie es nacheinander kommt:
Delphi-Quellcode:
var json, p1, p2: TJSONObject;
jsonArr: TJSONArray;
JsonToSend : TStream;
... und im Laufe des Codes (und es steht noch mehr dazwischen, was prop,cv füllt)
Delphi-Quellcode:
try
json := TJSONObject.Create;
json.AddPair(prop, TJSONString.create(cv));
try
p1 := TJSONObject.Create;
p2 := TJSONObject.Create;
p1.AddPair(prop, TJSONBool.Create(cv='true'))
p2.AddPair(prop, TJSONNumber.Create(cv));
try
jsonArr:= TJSONArray.Create;
jsonArr.Add(p1);
jsonArr.Add(p2);
json.AddPair('path', jsonArr);
finally
jsonArr.Free;
end;
finally
//jetzt brauche ich diese Objekte nicht mehr also..
p1.Free; // hier knallt es schon "Ungültige Zeigeroperation", ebenfalls mit .Destroy
p2.Free;
end;
try
JsonToSend := TStringStream.Create(json.ToString);
JsonToSend.Position := 0;
//...
finally
JsonToSend.Free; //kein Problem
end;
finally
json.free; // sonst knallt es auch hier
end;
Ich hatte meinen Code auch schon so, daß ich
p1 := json;
schrieb, in der Absicht, was in json steht, Fall-bedingt zu ergänzen. Das hat auch funktioniert, aber später hab ich es mir dann nicht mehr selbst erklären können, warum es funktioniert, denn ich fragte mich "was weise ich damit eigentlich zu?"...
RTFM: da steht was von Clone für eine Kopie. Aber nicht, wie ich die Zuweisung beispielsweise schreiben soll.
p1:=json.clone;
funktioniert nicht (wo kann ich den TJSONAncestor denn zuweisen??).
Ist p1 dann eine unabhängige Kopie? Also, wenn ich p1 etwas zuweise (AddPair), verändert das nichts in json?
Oder ist p1 ein Pointer auf die gleiche Adresse wie json? Wenn ich dann also p1 etwas zuweise (Addpair), steht es automatisch auch im json so drin, als hätte ich statt p1 auch gleich json schreiben können?
Prüfen kann ich die Zuweisungen, die aber funktionieren, nicht, denn wenn ich mit F7/F8 durch die
IDE steppe und auf die Variablen zeige, um den Wert zu sehen, steht da nur (0,0,0,0,0, ... $ad, ... ), was für mein Verständnis des Objekts wahnsinnig hilfreich ist
Also, viel Geschichte, aber zusammengefasst, was ich wissen möchte:
1) Was muss ich also wie freigeben in diesem Fall? Spielt die Reihenfolge eine Rolle?
1a) Wenn ich
p1.AddPair(prop, TJSONBool.Create(cv='true'));
schreibe, muss ich dann nicht auch noch TJSONBool.destroy machen (vielleicht gibt es hier ein Leak?), oder ist das nur eine Wertumwandlung?
2) Was weise ich damit eigentlich zu: p1:=json ?
2a) Wie muss die Zuweisung aussehen, wenn ich das Objekt mit den bisher gesammelten Daten kopieren will?
(einen String kann ich auf diese Weise kopieren und getrennt vom Original weiterarbeiten, aber wie mache ich das beim TJSONObject?)
3) Wenn ich also json.destroy schreibe und es ohne crash ausgeführt wird, warum sehe ich danach während des Debuggens in den "lokalen Variablen" das Objekt weiterhin mit allen Werten, als ob nichts geschehen wäre? Ich hätte erwartet, daß das Objekt dann nur noch () wäre!?