Zitat von
b1zZ:
Du musst erstmal XMLStringData zurück geben bevor du .Free ausführst.
Was hat das mit dem Result zu tun?
Zitat von
b1zZ:
Jedoch hab ich oft Probleme wenn ich ein Objekt oder in diesem Fall eine Stringlist Free'e.
Das Problem ist doch eher, dass du eine Instanz zurück gibst und wenn du diese noch vor der Rückgabe zerstörst, gibst du Müll zurück. Wenn du sehr sehr viel Glück hast, dann findest du in den zurückgegebenen Überresten noch ein paar Originale Strings.
Zitat von
b1zZ:
Im Prinzip brauchst du es nicht mal Free'en, denn es ist eine Lokale Variable, diese wird vom Delphi Speichermanager
freigegeben.
Auch Blödsinn, er muss es selbst freigeben. Beim Beenden des Prozesses werden alle alloziierten Resourcen von Windows wieder freigegeben, aber das was du beschreibst geschieht nicht. Das passiert bei Komponenten über den Owner, aber nicht bei solchen einfachen
VCL Klassen.
Delphi hat keinen Garbage-Kollektor!
@bundy:
Es wurde schon auf den Diskussions-Thread verwiesen und den empfehle ich auch. Grundlegend sollte man alloziierten Daten auf der gleichen Ebene wieder freigeben wie sie alloziiert wurden. Somit solltest du deine TStringList auch in der Procedure/Methode freigeben, was du aber nicht kannst, da sonst dein Rückgabewert weg wäre. Somit wäre die sauberste Lösung, dass du die TStringList aussen anlegst und beim Aufruf übergibst. Dann hast du erst gar nicht das Problem darüber nachdenken zu müssen.
Delphi-Quellcode:
function TForm1.catchItemXML(ItemNr:
string;
const AList: TStrings): TstringList;
var
req : IXMLHTTPRequest;
XMLStream:TMemoryStream;
XMLStringData:TStringList;
EdtUrlText:
string;
begin
XMLStream:=TMemoryStream.Create;
XMLStringData:=TStringList.Create;
try
req := CoXMLHTTP40.Create;
// Interface erzeugen
// in EdtURL steht die URL, die heruntergeladen werden soll
EdtUrlText:='
http://eu.wowarmory.com/item-info.xml?i='+ItemNr ;
req.open('
GET', EdtUrlText, False,
{Username} EmptyParam,
{Passwort} EmptyParam);
// eigenen Request-Header setzen
req.setRequestHeader('
ApplicationID', '
Test V1.0');
req.send(EmptyParam);
// Anfrage an Server senden und Antwort abwarten
// Nutzdaten anzeigen
XMLStringData.Text := req.responseText;
XMLStringData.Text:= StringReplace(req.responseText,'
UTF-8','
ISO-8859-1',[rfReplaceAll]);
XMLStringData.SaveToStream(XMLStream);
XMLStream.Seek(0,soBeginning);
AList.LoadFromStream(XMLStream);
finally
XMLStream.Free;
XMLStringData.Free;
end;
end;
Und der Aufruf dann:
Delphi-Quellcode:
var
lList: TStrings;
begin
...
lList := TStringList.Create;
try
catchItemXML('deinItem', lList);
...
mach was mit lList...
...
finally
lList.Free;
end;
end;
Und nochwas: Beachte die vom Compiler generierten Hinweise und Warnungen, sie sind nicht unwichtig! Du hast in deinem originalen Code hinweise, dass die Elemente XMLStream und XMLStringData möglicherweise nicht initialisiert worden seien. Damit hat Delphi auch vollkommen Recht! Also beachte die Hinweise!
Hintergrund: Du hast die Konstruktorenaufrufe innerhalb des try/finally Blockes gemacht und damit würde er mit einer
Exception in einem der beiden Konstruktoren in den finally Teil springen. Damit aber würde er im Finally teil den Destruktor aufrufen von zwei Instanzen die gar nicht existieren. Die Assigned() Prüfung im .Free greift nicht, da es beides lokale Variablen sind und diese somit zufälligen Inhalt haben und somit zufällige Adressen. Sie sind bei gut Glück zufälligerweise Nil, aber das ist pures Glück und ist sehr unwahrscheinlich.