Objekt als Funktionsergebnis, Freigabe

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Eclipticon
Beiträge: 292
Registriert: Sa 5. Feb 2011, 20:38
OS, Lazarus, FPC: Windows XP VirtualBox (FPC 2.6.4, Laz 1.2.4)
CPU-Target: 32Bit
Wohnort: Wien

Objekt als Funktionsergebnis, Freigabe

Beitrag von Eclipticon »

Schoenen Abend,

ich moechte folgenden Code verwenden:

Code: Alles auswählen

function Something: TObject;
var AObject: TObject
begin
AObject := TObject.Create;
AObject.Something(bla);
Result := AObject;
end;
frage mich jetzt aber, wo ich AObject wieder freigeben muss ... innerhalb der Funktion? Diese Logik (und auch die, nach der Objekte automatisch freigegeben werden) ist mir noch nicht ganz klar ...

Vielen Dank!

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2817
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Objekt als Funktionsergebnis, Freigabe

Beitrag von m.fuchs »

Eclipticon hat geschrieben:

Code: Alles auswählen

function Something: TObject;
var AObject: TObject
begin
AObject := TObject.Create;
AObject.Something(bla);
Result := AObject;
end;
frage mich jetzt aber, wo ich AObject wieder freigeben muss ... innerhalb der Funktion? Diese Logik (und auch die, nach der Objekte automatisch freigegeben werden) ist mir noch nicht ganz klar ...
Die Frage ist ja: was soll deine Funktion machen? Ich vermute jetzt mal, sie erzeugt ein neues Objekt, tut irgendetwas damit und gibt es dann nach "draußen". Sowas nennt man im allgemein Factory Pattern und ist sehr beliebt um ein Objekt zu erzeugen und mit bestimmten Werte zu versehen.
Nun willst du aber außerhalb deiner Funktion (nämlich von der Stelle aus wo du sie aufgerufen hast) mit diesem Objekt etwas tun. Wenn du dieses Objekt jetzt aber schon innerhalb der Funktion freigibst, kann man außerhalb nichts mehr mit diesem Objekt anfangen. Du zerstörst es dann also erst, wenn du wirklich damit fertig bist es zu benutzen.

Ein Beispiel, was deine Methode verwendet:

Code: Alles auswählen

var
  Dumdidum: TObject;
begin
  Dumdidum := Something;  //hier wird dann deine Funktion aufgerufen und das in ihr erzeugte Objekt entgegengenommen
  Dumdidum.MachWas;
  Dumdidum.MachWasAnderes;
  FreeAndNil(Dumdidum);  //nun ist das Objekt zerstört und Dumdidum zeigt auf nil;
end.
hth
Micha
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Objekt als Funktionsergebnis, Freigabe

Beitrag von MAC »

gar nicht.

Du übergibst in lazarus ( delphi ist es glaub ich genauso) keine objekte sondern nur ein pointer (wegweiser) auf das objekt.

Also wird in der Funktion ein objekt erstellt. Something ausgeführt und als ergebnis kommt ein pointer auf das aobjekt raus. wenn du jetzt in der funktion an sich das objekt freigeben würdest und folgenden code benuzen würdest würde ein fehler auftauchen, weil bobjekt und aobjekt auf das gleiche TObjekt verweisen. Wenn das aobjekt freigeben wird ist das bobjekt genauso freigegeben, nur das in der variable bobjekt noch nen üngültiger pointer steckt...

Code: Alles auswählen

var
bobjekt:TObjekt;
begin
bobjekt := something;
bobjekt.irgendwastolles
end;
Im endeffekt musst du das also dann freigeben wenn du es nicht mehr brauchst. nicht innerhalb der funktion weil dieso sonnst nil zurückgibt.

edit: m.fuchs war schneller :)

Code: Alles auswählen

Signatur := nil;

Eclipticon
Beiträge: 292
Registriert: Sa 5. Feb 2011, 20:38
OS, Lazarus, FPC: Windows XP VirtualBox (FPC 2.6.4, Laz 1.2.4)
CPU-Target: 32Bit
Wohnort: Wien

Re: Objekt als Funktionsergebnis, Freigabe

Beitrag von Eclipticon »

Danke, m.fuchs und MAC.

Konkret wird das Funktionsergebnis (TStringList) an eine Komponente uebergeben, womit ich mich (soweit ich es richtig verstehe) nicht mehr um die Freigabe dieses Objekts kuemmern muss.

Sorry, ich komme jedes Mal ins Schwitzen, wenn ich ein .Create ohne ein .Free sehe :lol:

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Objekt als Funktionsergebnis, Freigabe

Beitrag von MAC »

kommt drauf an wie gut die andere komponente programmiert ist...
empfehlenswert: einfach mal taskmanager öffnen, benutzer arbeitsspeicher vom programm anzeigen lassen - dann das selbe tausend mal ausführen lassen und schauen ob sich dort was ändert, wenn sich dort was groß ändert gibts grund zur sorge...

Code: Alles auswählen

Signatur := nil;

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2817
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Objekt als Funktionsergebnis, Freigabe

Beitrag von m.fuchs »

Eclipticon hat geschrieben:Konkret wird das Funktionsergebnis (TStringList) an eine Komponente uebergeben, womit ich mich (soweit ich es richtig verstehe) nicht mehr um die Freigabe dieses Objekts kuemmern muss.
Vorsicht, da kannst du in ganz üble Probleme kommen:

1.) Wie MAC schon schrieb muss die Komponente das angehängte Objekt ja nicht mit entfernen.

2.) Wenn an der Komponente schon ein Objekt hängt (was automatisch im Create der Komponente erzeugt wird) und du weist der entsprechenden Eigenschaft dein Objekt zu, was passiert dann mit dem ursprünglichen Objekt?

Code: Alles auswählen

var
  Komponente: TKomponente; //sagen wir mal die hat eine Eigenschaft namens StringList
  Objekt: TStringList;
begin
  Komponente := TKomponente.Create; //eine neue Komponente wird erzeugt, dabei wird auch ihre Eigenschaft StringList mit einer neuen TSTringList belegt
  Objekt := TStringList.Create;
  Komponente.StringList := Objekt; //die Eigenschaft verweist nun auf die von dir erzeugte TStringList, die ursprüngliche ist immer noch da aber es gibt keinen Verweis mehr darauf
  Komponente.Free; //beim Aufräumen wird die von dir erzeugt TStringList mit zerstört, die ursprüngliche oxidiert immer noch im Speicher herum
end.
Und schwupps ist es da, das Speicherleck.

3.) Bist du dir sicher, dass die Zuweisung deiner TStringListe an die Komponente wirklich dein Objekt daran bindet? Es kann ja auch sein, dass die Set-Methode der Property bloss den Inhalt kopiert. (Ist das nicht zum Beispiel beim TMemo so?). In so einem Fall musst du dein Objekt auch danach töten.

Also, da kann man eine Menge Fehlerquellen einbauen und bemerkt es vielleicht nicht einmal. Manche Speicherlecks kommen erst nach Monaten Laufzeit zum Vorschein. Minimieren kann man sowas in dem man ein wenig Speicherprofiling betreibt. Hier ganz gut beschrieben: http://wiki.freepascal.org/Profiling#He ... C_LineInfo" onclick="window.open(this.href);return false;
Eclipticon hat geschrieben:Sorry, ich komme jedes Mal ins Schwitzen, wenn ich ein .Create ohne ein .Free sehe :lol:
Sowas soll es ja auch nie geben. Nur wird gelegentlich das Free irgendwo anders aufgerufen.

mfg
Micha
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten