TSringList als Funktions-Rückgabe sinnvoll?

Für Fragen von Einsteigern und Programmieranfängern...
Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von photor »

Hallo Forum,

ich bin mal wieder dazu verdammt, in fremden Code Fehler auszumerzen (Absturz wegen Speicherfehler) und finde an mehreren Ecken sowas hier:

Code: Alles auswählen

function FindMaxMin(Data_List: TStringList): TStringList;
var
  i: integer;
  Max, Min, Current_Value: double;
begin
  for i:=0 to Data_List.Count -1 do
  begin
    Current_Value := StrToFloat(Data_List[i]);
 
 [...]
 
  Data_List.Insert(0, FloatToStr(Min));
  Data_List.Insert(0, FloatToStr(Max));
 
  Result := Data_List;
end;
Also es wird eine Funktion definiert, die als Parameter eine TStringList Data_List bekommt, mit den Doubles(!) darin irgendwas anstellt (hier Minimum und Maximum suchen, die dann vorne an die Liste gepackt werden) und dann exakt diese StringList wird als Result zurückgegeben.

Mit dem Anhängen vom Min und Max an den Anfang kann ich ja noch leben (muss man nur wieder beheben). Aber eine Liste, die als Parameter in eine Funktion hinein geht als Rückgabewert ... ? Kann das gut gehen?

Ich hätte gedacht, dass man in diesem Fall besser eine Procedure nimmt und Data_List als var deklariert, so dass diese direkt manupuliert werden kann.

Oder übersehe ich hier was?

Ciao,
Photor

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von theo »

Nö, das da finde ich auch recht irre.
Var wäre normalerweie das Beste, aber hier wirst du den Object Pointer ja nicht verändern, also geht auch ohne var.
Im Prinzip kannst du daraus, so wie es ist, eine Prozedur machen und Result:= streichen.
Allenfalls geht ein Rückgabewert von TObject noch, wenn das Object in der Funktion selber created wird, aber schön ist das auch nicht.
So wie in deinem Beispiel ist's mMn blöd. Aber "funktionieren" tut es schon.

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von photor »

Moin,

Ok, also genau genommen ist nicht mal das var nötig (und also funktioniert es genau deshalb).

Das werde ich dann mal so, wie du sagst, umsetzen. Es wird aber nicht der Grund für all die Speicherlecks gewesen sein (da habe ich noch genug haarsträubendes gefunden! .Free kommt fast nicht vor in dem Code).

Ich war mir bei dieser Konstruktion ziemlich sicher, dass das Mumpitz ist (aber nicht sicher genug - daher die Frage hier).

Merci,
Photor

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Socke »

photor hat geschrieben:
Di 25. Jan 2022, 16:30
Also es wird eine Funktion definiert, die als Parameter eine TStringList Data_List bekommt, mit den Doubles(!) darin irgendwas anstellt (hier Minimum und Maximum suchen, die dann vorne an die Liste gepackt werden) und dann exakt diese StringList wird als Result zurückgegeben.
Es gibt durchaus das Konzept des Method Chainings. Es wird in Pascal nur sehr selten angewandt. Problematisch ist wie du schon bemerkt hast die (manuelle) Speicherverwaltung. Mit referenzgezählten Interfaces könnte man soetwas tatsächlich sinnvoller umsetzen machen. TStringList gehört also defnitiv nicht zu den Anwendungsgebieten des Method Chainings.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von theo »

Socke hat geschrieben:
Di 25. Jan 2022, 18:54
Es gibt durchaus das Konzept des Method Chainings. Es wird in Pascal nur sehr selten angewandt.
Ja, da habe ich auch noch kurz drüber nachgedacht, aber für den vorliegenden Fall, schien mir das zu weit hergeholt.
Das funktioniert ja auch nur, wenn eine Methode einer Klasse immer wieder ein self zurück gibt.

Nur mal kurz zusammengehackt:

Code: Alles auswählen

type

  TTestList = class(TStringList)
    public
    function AddString(item:String):TTestList;
    function Save(fn:String):TTestList;
    end;
...

{ TTestList }

function TTestList.AddString(item: String): TTestList;
begin
  Self.Add(item);
  Result:=Self;
end;

function TTestList.Save(fn: String): TTestList;
begin
   Self.SaveToFile(fn);
   Result:=Self;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  TTestList.Create.AddString('eins').AddString('zwei').Save('test.txt').Free;
end;   

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Winni »

Hi!

Wen es interessiert:

Method chaining in Delphi mit helpern.
Ausnahmweise auf deutsch:

https://www.youtube.com/watch?v=XXrFtNa1UIE

Winni

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Winni »

Hi!

Nochmals zurück zum eigentlichen Thema:

Eine TStringList als Funktions-Resultat kann durchaus sinnvoll sein:

* Wenn man eine Stringlist aufbaut oder verändert
* Wenn man aus zwei Stringlisten eine dritte aufbaut, z.B. die Shnittmenge oder Vereinigung

Nur mal angemerkt.

Winni

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 331
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon (Windows wenn notwendig), Lazarus 3.0 FPC 3.3.1

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Niesi »

Wenn eine dritte aufgebaut wird: ja klar, verstehe ich.
Wenn ich aber ein Objekt "uebergebe" und dasselbe Objekt von der Aufrufenden weiter verwendet wird, dann reicht doch eine Procedure.
Oder uebersehe ich etwas?

( ich arbeite naemlich genau so, nicht mit tStringlist, sondern mit anderen Objekten ... )
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Winni »

Hi!

Die Anwendung ist sinnvoll in folgendem Szenario:

StringListA sind die Original-Daten und du willst jetzt z.B. filtern, z.B. Name von A bis E oder PLZ von 20000 bis 29999 oder oder ....

Da darf die ursprüngliche Stringliste nicht zerstört werden, weil sie ja für weitere Operationen zur Verfügung stehen muss. Also muss eine zweite Stringliste angelegt werden. Praktischerweise als Funktionsergebnis.

Winni

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von wp_xyz »

Winni hat geschrieben:
Do 27. Jan 2022, 13:08
Praktischerweise als Funktionsergebnis.
Dann aber mit einem dicken Kommentar dahinter, dass man sie wieder freigeben muss. Wenn ich eine Funktion mit harmlosem Namen wie FindMaxMin() aufrufe, dann ahne ich nicht, dass ich hier ein Speicherleck erzeuge. Oder ein "Create" in den Namen einbauen, z.B. CreateMaxMinStringList(...)

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Winni »

Irre: Objecte müssen freigegeben werden. Ganz was Neues!

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von six1 »

Instanzen von Objekten...
nicht den Bauplan, sondern das mit dem Bauplan geschaffene...
Gruß, Michael

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von photor »

Winni hat geschrieben:
Do 27. Jan 2022, 10:10
Hi!

Nochmals zurück zum eigentlichen Thema:

Eine TStringList als Funktions-Resultat kann durchaus sinnvoll sein:

* Wenn man eine Stringlist aufbaut oder verändert
* Wenn man aus zwei Stringlisten eine dritte aufbaut, z.B. die Schnittmenge oder Vereinigung
Genau so hatte ich es beim ersten Lese auch gesehen/gedacht - bis mir halt auffiel, dass das hier nicht so war. Im oben gezeigten Fall ist es so, dass aus der ursprünglichen Liste Einträge raus geschmissen werden sollen. Das kann man auf der Originalliste machen - und wird ja auch so gemacht, nur dass die dann eben auch noch als result zurück gegeben wird.

Aber wenn dir Originalliste NICHT verändert werden soll? Dann muss ich sowas machen:

Code: Alles auswählen

neueListe := TStringList.Create;
Mache ich das besser IN der Funktion mit

Code: Alles auswählen

Result := neueListe;
Dann kann ich neueListe aber nicht in der Funktion freigeben. Das muss ich dann irgendwann später machen - spätestens in

Code: Alles auswählen

TMainForm.Close
Oder mache ich das besser AUSSERHALB der Funktion, dann

Code: Alles auswählen

begin
  neueListe := TStringList.Create;
  neueListe := MeineFunktion(Data_List);
  // mache weiter mit neueListe
  ...
  neueListe.Free;
end;
Ist mir noch nicht klar, was besser ist.

Ciao,
Photor

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von theo »

photor hat geschrieben:
Do 27. Jan 2022, 17:06
Ist mir noch nicht klar, was besser ist.
Für mich ist klar besser, auf der gleichen Ebene zu createn wie man freigibt.
Einer Prozedur kann man natürlich auch zwei Parameter übergeben, eine Eingabe- und eine in der Prozedur veränderte Ausgabe-StringList, welche beide vorher schon created wurden.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TSringList als Funktions-Rückgabe sinnvoll?

Beitrag von Winni »

Hi!

Also das ist doch ein grundlegendes Prinzip:

Wenn das Funktions-Resultat nicht ein "einfacher" Datentyp ist, so muss die rufende Funktion das Resultat freigeben. Einfache Datentypen sind in dieser Definition alles, was nicht explizit erzeugt werden muss, also z.B. auch eine Record oder ein array of irgendwas.

Wenn das eine StringList, eine Bitmap oder sonstwas Erzeugtes ist - es muss freigegeben werden.

Winni

Antworten