Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi function mit TStringList Result (https://www.delphipraxis.net/111886-function-mit-tstringlist-result.html)

bundy 11. Apr 2008 08:45


function mit TStringList Result
 
hi DP ,

ich hab mal ne Frage :?:
muss ich wenn ich einen Function habe die als Result eine TStringList hat, diesen Result auch wieder freigeben ?

Delphi-Quellcode:
function TForm1.catchItemXML(ItemNr: string): TstringList;
var
   req : IXMLHTTPRequest;
   XMLStream:TMemoryStream;
   XMLStringData:TStringList;
    EdtUrlText:string;
begin
  try
   XMLStream:=TMemoryStream.Create;
   XMLStringData:=TStringList.Create;
   Result:=TStringList.Create;                     <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Diesen DA

   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);
   Result.LoadFromStream(XMLStream);
  finally
    XMLStream.Free;
    XMLStringData.Free;
                   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Muss der da .free ? oder habe ich sonst keinen result ?
  end;


end;


lg
bundy

b1zZ 11. Apr 2008 08:49

Re: function mit TStringList Result
 
Du musst erstmal XMLStringData zurück geben bevor du .Free ausführst.
Jedoch hab ich oft Probleme wenn ich ein Objekt oder in diesem Fall eine Stringlist Free'e.
Im Prinzip brauchst du es nicht mal Free'en, denn es ist eine Lokale Variable, diese wird vom Delphi Speichermanager
freigegeben.

Also:
Delphi-Quellcode:
  ...
  Result:= XMLStringData;
end;

DeddyH 11. Apr 2008 08:53

Re: function mit TStringList Result
 
Dazu gab es schon einmal einen langen Thread hier. An Deiner Stelle würde ich die Stringliste als Parameter übergeben.

bundy 11. Apr 2008 08:57

Re: function mit TStringList Result
 
aha allso ist es nicht notwendig. ich wusste nur nicht ob mein Result dann noch einen Result hat, wenn ich ihn freigebe.

Delphi-Quellcode:

try
result:= .......
finally
Result.free;
end;

danke für die schnelle antwort

lg
bundy

RavenIV 11. Apr 2008 10:17

Re: function mit TStringList Result
 
Zitat:

Zitat von DeddyH
Dazu gab es schon einmal einen langen Thread hier. An Deiner Stelle würde ich die Stringliste als Parameter übergeben.

Würde ich auch so machen.
Die Stringlist in der aufrufenden Methode oder als Member anlegen.
Dann die Stringlist als Parameter an die Funktion übergeben (evtl. als var-Parameter).
Somit brauchst Du Dich in der Funktion nicht um die StringList kümmern -> ein Problem weniger.

DeddyH 11. Apr 2008 10:22

Re: function mit TStringList Result
 
Var-Parameter sind bei Objekten nicht nötig, da es ja schon Zeiger sind. Ich habe den von mir angesprochenen Thread noch einmal herausgesucht: Klick

Muetze1 11. Apr 2008 10:27

Re: function mit TStringList Result
 
Zitat:

Zitat von b1zZ
Du musst erstmal XMLStringData zurück geben bevor du .Free ausführst.

Was hat das mit dem Result zu tun?

Zitat:

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:

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.

RavenIV 11. Apr 2008 10:30

Re: function mit TStringList Result
 
Zitat:

Zitat von DeddyH
Var-Parameter sind bei Objekten nicht nötig, da es ja schon Zeiger sind. Ich habe den von mir angesprochenen Thread noch einmal herausgesucht: Klick

Das stimmt.
Aber var-Parameter erhöhen die Übersichtlichkeit.
Man sieht sofort in der Deklaration, dass hier etwas zurückgegeben wird.
Und das eine Wort tut auch keinem weh, vermutlich optimiert der Compiler das eh weg.

Muetze1 11. Apr 2008 10:34

Re: function mit TStringList Result
 
Zitat:

Zitat von RavenIV
Aber var-Parameter erhöhen die Übersichtlichkeit.
Man sieht sofort in der Deklaration, dass hier etwas zurückgegeben wird.

Ganz im Gegenteil. Mich würde das nur noch mehr verunsichern, da ich damit rechnen muss, dass mir die Funktion meine Instanz zerschiesst, auf NIL setzt oder eine ganz eigene Instanz zurück gibt. Somit habe ich das Problem, dass ich vielleicht noch die ganzen anderen Referenzen des Objektes vor dem Aufruf korrigieren muss, da ich nicht weiss ob die Funktion dies macht. Mit Const weiss ich definitiv, dass sie das nicht macht bzw. kann. Auch hat VAR den Nachteil, dass ich niemals eine Property angeben kann bei einem Aufruf. Das hast du damit automatisch ausgeschlossen. Also könnte ich niemals z.B. ListBox1.Items beim Aufruf angeben. Somit sehe ich in der Vorgehensweise nur Nachteile bzw. sogar eher Doppeldeutigkeiten, da ich nicht mehr weiss, ob die Methode wirklich meine Instanz verändert oder nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:12 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-2025 by Thomas Breitkreuz