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 Result ist Klasse Wie freigeben? (https://www.delphipraxis.net/75083-function-result-ist-klasse-wie-freigeben.html)

Alexander Roth 14. Aug 2006 09:42


Function Result ist Klasse Wie freigeben?
 
Hi @all,

also ich habe so was:
Delphi-Quellcode:
function a(old:Tstringlist):Tstringlist;
begin
  result:=Tstringlist.Create;
  result.Clear;

//  result.Free;
end;
Also ich weis nicht wie ich das wieder freigeben soll. (oder wird das vielleicht sogar automatisch freigegeben?)
und wenn man es nicht created dann zeigt anscheinend result auf old.


Natürlich könnte ich das umgehen
Delphi-Quellcode:
procedure a(var new:Tstringlist; old:Tstringlist);
begin
  new.clear;
end;
aber ich möchte wissen wie man es anders hinkriegt.

Wisst ihr wie?

Danke im Voraus

Khabarakh 14. Aug 2006 09:51

Re: Function Result ist Klasse Wie freigeben?
 
Rückgabewerte einer Funktion muss der Aufrufer dieser Funktion freigeben.

Jürgen Thomas 14. Aug 2006 09:58

Re: Function Result ist Klasse Wie freigeben?
 
Zitat:

Zitat von Alexander Roth
aber ich möchte wissen wie man es anders hinkriegt.

Was denn eigentlich?

Du hast unter "old" eine Stringliste. Deine erste Variante:
Zitat:

Zitat von Alexander Roth
Delphi-Quellcode:
function a(old:Tstringlist):Tstringlist;
begin
  result:=Tstringlist.Create;
  result.Clear;
//  result.Free;
end;

erzeugt eine neue Stringliste (diese ist per se leer); dann leerst Du sie und gibt sie als Ergebnis (result) zurück. "Dort" kann dann damit gearbeitet werden.

Zitat:

Zitat von Khabarakh
Rückgabewerte einer Funktion muss der Aufrufer dieser Funktion freigeben.

Du musst sie also "irgendwo" selbst wieder freigeben, z.B.:
Delphi-Quellcode:
//  irgendeine Prozedur
var sListeAlt: TStringList;
    sListeNeu: TStringList;
...
//  sListeAlt muss bereits erzeugt sein
  sListeNeu := a(sListeAlt);
...
  sListeNeu.Free;
Zitat:

Zitat von Alexander Roth
und wenn man es nicht created dann zeigt anscheinend result auf old.

Nein: Wenn der Befehl "result:=Tstringlist.Create;" nicht ausgeführt werden soll, zeigt Result "irgendwohin" und führt in "irgendeiner Prozedur" sehr schnell zu Zugriffsverletzungen.

Zitat:

Zitat von Alexander Roth
Natürlich könnte ich das umgehen
Delphi-Quellcode:
procedure a(var new:Tstringlist; old:Tstringlist);
begin
  new.clear;
end;

Bei diesem Verfahren wird "new" geleert (natürlich auch mit Exception, wenn es nicht vorher erzeugt wurde) und sonst nichts - es gibt keinen Zusammenhang mit "old".

Nebenbei: Eine Stringliste muss nicht als "var" deklariert werden; man kann sie auch als "const" manipulieren. (Ich weiß nicht genau warum; vielleicht unterscheiden sich da auch Delphi-Versionen.)

Also meine Hauptfrage bleibt: Was willst Du eigentlich? Jürgen

Alexander Roth 14. Aug 2006 10:08

Re: Function Result ist Klasse Wie freigeben?
 
Zitat:

Zitat von Jürgen Thomas
Also meine Hauptfrage bleibt: Was willst Du eigentlich? Jürgen

Ja das ist ja auch nur ein Beispiel. Das da nicht gerade viel Inhalt drin ist, ist ja klar. (Und mit old wird halt was anderes gemacht)


Zitat:

Zitat von Jürgen Thomas
Du musst sie also "irgendwo" selbst wieder freigeben, z.B.:
Delphi-Quellcode:
//  irgendeine Prozedur
var sListeAlt: TStringList;
    sListeNeu: TStringList;
...
//  sListeAlt muss bereits erzeugt sein
  sListeNeu := a(sListeAlt);
...
  sListeNeu.Free;

Das wollte ich wissen. :thumb:
Danke für eure Hilfe.

Tschüss :hi:

Gruß Alexander

xaromz 14. Aug 2006 10:11

Re: Function Result ist Klasse Wie freigeben?
 
Hallo,
Zitat:

Zitat von Jürgen Thomas
Zitat:

Zitat von Alexander Roth
und wenn man es nicht created dann zeigt anscheinend result auf old.

Nein: Wenn der Befehl "result:=Tstringlist.Create;" nicht ausgeführt werden soll, zeigt Result "irgendwohin" und führt in "irgendeiner Prozedur" sehr schnell zu Zugriffsverletzungen.

Das stimmt nicht ganz. Wenn in einer Funktion nichts gemacht wird, dann zeigt Result tatsächlich auf das erste Argument (in diesem Fall Old), da sowohl das erste Argument als auch Result in EAX liegen.

Aber zurück zum Topic:
Grundsätzlich gibt es immer zwei Varianten: Entweder ein Objekt als Argument übergeben (nicht als var) oder als Result erhalten. In beiden Fällen ist aber die aufrufende Funktion dafür verantwortlich, dass das Objekt am Ende freigegeben wird. Der einzige Unterschied besteht hier in der Lesbarkeit. Denn bei der Variante "Argument" muss ich das Objekt vorher selbst anlegen und weiß damit auch, dass ich es selbst zerstören muss. Bei der anderen Variante muss ich das zwar auch, aber es ist nicht offensichtlich. Außerdem kann ich mir bei einer Blackbox (was eine Funktion möglichst sein sollte) eben nicht sicher sein, ob ich nicht nur eine Referenz auf ein internes Objekt erhalte. Das darf ich dann nämlich nicht freigeben.
Die oben angesprochene Variante mit var, bei der das Objekt in dern Funktion erzeugt wird, ist nichts anderes als eine Variante von "Result".

Gruß
xaromz

jbg 14. Aug 2006 11:26

Re: Function Result ist Klasse Wie freigeben?
 
Zitat:

Zitat von xaromz
Das stimmt nicht ganz. Wenn in einer Funktion nichts gemacht wird, dann zeigt Result tatsächlich auf das erste Argument (in diesem Fall Old), da sowohl das erste Argument als auch Result in EAX liegen.

Und was wenn ich stdcall oder cdecl angebe? Result ist als Undefined anzunehmen. Alles andere wäre Ausnutzung von mehr oder weniger zufälligen Zuständen, die sich jederzeit ändern können.

Zitat:

Bei der anderen Variante muss ich das zwar auch, aber es ist nicht offensichtlich. Außerdem kann ich mir bei einer Blackbox (was eine Funktion möglichst sein sollte) eben nicht sicher sein, ob ich nicht nur eine Referenz auf ein internes Objekt erhalte. Das darf ich dann nämlich nicht freigeben.
Die Offensichtlichkeit bekommt man in diesem Fall nur, wenn man passende Namen für die Funktion vergibt.

Persönlich nutze ich dabei folgende Namensgebung:
Eine Funktion die "function CreateNamenList: TStrings" heißte erzeugt die Liste und der Aufrufer muss für deren Freigabe sorgen. Heißt sie hingegen "function GetNamenList: TStrings" ist klar, dass der Aufrufer sich um das Freigeben keine Sorgen machen muss.

xaromz 14. Aug 2006 12:21

Re: Function Result ist Klasse Wie freigeben?
 
Hallo,
Zitat:

Zitat von jbg
Und was wenn ich stdcall oder cdecl angebe? Result ist als Undefined anzunehmen. Alles andere wäre Ausnutzung von mehr oder weniger zufälligen Zuständen, die sich jederzeit ändern können.

schon klar.

Zitat:

Zitat von jbg
Die Offensichtlichkeit bekommt man in diesem Fall nur, wenn man passende Namen für die Funktion vergibt.

Persönlich nutze ich dabei folgende Namensgebung:
Eine Funktion die "function CreateNamenList: TStrings" heißte erzeugt die Liste und der Aufrufer muss für deren Freigabe sorgen. Heißt sie hingegen "function GetNamenList: TStrings" ist klar, dass der Aufrufer sich um das Freigeben keine Sorgen machen muss.

Wenn man das im Styleguide so definiert, kann das auch funktionieren.

Gruß
xaromz


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:14 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