AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Funktionsrückgabe freigeben

Ein Thema von Guido Eisenbeis · begonnen am 9. Mär 2007 · letzter Beitrag vom 11. Mär 2007
Antwort Antwort
Seite 3 von 4     123 4      
Guido Eisenbeis

Registriert seit: 9. Apr 2006
389 Beiträge
 
Delphi 10.3 Rio
 
#21

Re: Funktionsrückgabe freigeben

  Alt 10. Mär 2007, 20:33
Hallo Angel4585.

Zitat von Angel4585:
Dazu muss ich sagen das ich das Problem nicht verstehe... den Speicher freigeben den eine Funktion belegt??
Was gibt es daran nicht zu verstehen?
Die Frage ist: Wie gebe ich den Speicher frei, den ein Funktion belegt, die ein Objekt zurückgibt?

Ich habe den Eindruck, dass du das schon richtig verstanden hast:

Zitat von Angel4585:
Jedes Mal wenn die Funktion aufgerufen wird wird auch ein neues Object erzeugt, d.h. nach dem 10. Aufruf der Funktion sind es 10 Objekte.
Und die sollten wieder freigegeben werden, wenn man einen ordentlichen Programmierstil praktiziert!


Zu deinem Beispiel mit der Klasse "TMeinObject":

Zunächst mal ist es recht geschickt gemacht! Dadurch entsteht der Eindruck als würdest du auf meine Frage antworten. Die Frage war jedoch: Wie sieht dein "Tu was.." aus, wenn du das OBJEKT aus der Funktionsrückgabe im With-Block benutzen willst.

Du hast in deiner Antwort jedoch einfach ein "Unter-Objekt" genommen! Das war NICHT die Frage! Du benutzt innerhalb des With-Blocks ein (Unter-)Objekt des Rückgabe-Objekts. In diesem Fall das Objekt einer Property. Wie gesagt, es war NICHT die Frage, wie ein ein Teil (Property) des Rückgabe-Objekts im With-Block benutzt werden kann, sondern wie das Rückgabe-Objekt selbst im With-Block benutzt werden kann.

Um jedoch auf das eigentliche Thema zurückzukommen:

Du hast in deinem Beispiel das Icon zwar (leer) erstellt, ihm aber kein Icon zugewiesen. Dadurch werden (fast) keine Ressourcen belegt. Der Sinn einer solchen Funktion ist natürlich, ein Icon auch zu benutzen/füllen. Wenn du das jedoch in deinem "TMeinObject"-Beispiel tust, sind wir so weit wie vorher!

Delphi-Quellcode:
type
  TMeinObject = class(TObject)
    private
      FIcon : TIcon;
    public
      constructor Create;
      property ObjectIcon : TIcon read FIcon write FIcon;
    end;

constructor TMeinObject.Create;
begin
  FIcon:=TIcon.Create;
end;

function IchGebeEinObjectZurueck : TMeinObject;
begin
  Result:=TMeinObject.Create;
  Result.ObjectIcon.LoadFromFile('C:\Test.ico'); // <- Speicher belegen
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
with IchGebeEinObjectZurueck do
  try
    // Icon aus Exe auslesen und Image zuweisen
    Image1.Picture.Graphic := ObjectIcon
  finally
    Free;
  end;
end;
Nun ergibt sich wieder das gleiche Ergebnis: Klickst du vielfach auf den Button, ist im Taskmanager ein langsames aber stetiges Ansteigen der Speicherbelegung zu erkennen!


Aber nun genug davon. Wir haben offensichtlich alle (Thread-Teilnehmer) die Prozedur-Lösung zum Favoriten "erkoren"!
Einschließlich dir selbst:

Zitat von Angel4585:
Wenn ich jedoch das ganze mit einer Prozedur erledige in der das Object falls es schon erzeugt wurde freigebe und danach erzeuge ist klar das es immer nur ein einziges bleibt.
Fazit:

Es wurden Möglichkeiten zur Freigabe von Objekt-Funktionsrückgaben in diesem Thread gezeigt. Jedoch können diese nicht wirklich überzeugen. Die Prozedur-Lösung hingegen stellt eine saubere, übersichtliche Möglichkeit dar.

Damit ist meine Frage beantwortet. Nochmals danke an alle!

Guido.
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#22

Re: Funktionsrückgabe freigeben

  Alt 10. Mär 2007, 22:29
beantwortet oder nicht

es ist egal wie ein Objekt erzeugt wird, ob als Resultat einer Funktion oder einfach so, freigeben muss man es so oder so, also wenn du das Resultat der Funktion einer Variablen zuweist und diese dann freigibst, oder wie ich direkt mit dem With try finally free end arbeitest kommts auf das selbe raus.

was ich nicht verstehe ist was es mit der Funktion auf sich hat, ist doch nichts anderes..

Delphi-Quellcode:
//Das
FIcon:=TIcon.Create;
//ist das selbe wie das

function Irgendwas : TIcon;
begin
Result:=TIcon.Create;
end;

FIcon:=Irgendwas;
Ich nutze die Funktion wenn ich beim Erzeugen eines Objects jedesmal einen Schritt durchführen muss und die Variable selbst jedoch nicht benötige, also nur die "Unterobjekte".

Zum Beispiel(das verwende ich tatsächlich) wenn ich eine Datenbank anwendung habe und nur eine kurze Abfrage losschicke, dann hab ich nciht eine dauerhafte komponente irgendwo rumliegen, sondern erzeuge meine Query nur wenn ich sie brauche:
Delphi-Quellcode:
function MyQuery(ASQL : string) : TZQuery;
begin
Result:=TZQuery.Create(nil);
Result.Connection:=DataModule1.ZConnection1;
Result.SQL.text:=ASQL;
end;

//Dann spar ich mir dafür an anderen stellen jede Menge Code:
with MyQuery('select * from tabelle where id="12345"') do
  try
    Active:=True;//Oderd auch Open, ExecSQL etc.
    //Und dann alles verarbeiten
  finally
    Free;//Und die temporäre Query freigeben.
    end;
Ist jetzt nur ein Beispiel, aber für solche Anwendungen finde ich es einfach praktisch
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#23

Re: Funktionsrückgabe freigeben

  Alt 10. Mär 2007, 23:06
Hallo,
Zitat von Guido Eisenbeis:
Delphi-Quellcode:
type
  TMeinObject = class(TObject)
    private
      FIcon : TIcon;
    public
      constructor Create;
      property ObjectIcon : TIcon read FIcon write FIcon;
    end;

constructor TMeinObject.Create;
begin
  FIcon:=TIcon.Create;
end;

function IchGebeEinObjectZurueck : TMeinObject;
begin
  Result:=TMeinObject.Create;
  Result.ObjectIcon.LoadFromFile('C:\Test.ico'); // <- Speicher belegen
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
with IchGebeEinObjectZurueck do
  try
    // Icon aus Exe auslesen und Image zuweisen
    Image1.Picture.Graphic := ObjectIcon
  finally
    Free;
  end;
end;
Nun ergibt sich wieder das gleiche Ergebnis: Klickst du vielfach auf den Button, ist im Taskmanager ein langsames aber stetiges Ansteigen der Speicherbelegung zu erkennen!
Das ist ja auch klar. Das TMeinObjekt wird zwar freigegeben, das darin erstellte TIcon aber nicht. Du hast also ein Speicherleck erzeugt. Wenn Du im Destruktor von TMeinObject das TIcon aufräumst, steigt auch der Speicher nicht an.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Guido Eisenbeis

Registriert seit: 9. Apr 2006
389 Beiträge
 
Delphi 10.3 Rio
 
#24

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 00:10
Hallo xaromz.

Schon lange nichts mehr von dir gehört! Es sei denn, in VB-Kreisen gibt es einen anderen xaromz!? Ansonsten: *freu*

Zitat von xaromz:
Hallo,
Das ist ja auch klar. Das TMeinObjekt wird zwar freigegeben, das darin erstellte TIcon aber nicht. Du hast also ein Speicherleck erzeugt. Wenn Du im Destruktor von TMeinObject das TIcon aufräumst, steigt auch der Speicher nicht an.
Danke! Genau das habe ich gemeint!


@Angel4585

Willst du dich jetzt an dem "Unterobjekt" festbeißen? Dann solltest du wohl einen eigenen Thread aufmachen! In diesem Thread geht es um das komplette Objekt einer Funktions-Rückgabe!

Nehmen wir das Beispiel von ganz am Anfang und gestalten es der Klarheit wegen noch ein wenig einfacher:

Delphi-Quellcode:
function GetFileIcon(AFileName: string): TIcon;
begin
  Result := TIcon.Create;
  Result.LoadFromFile(AFileName);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Icon aus Exe auslesen und Image zuweisen
  Image1.Picture.Graphic := GetFileIcon('C:\Test.ico');
end;
Wie willst du das mit dem "with try finally free end" lösen? Und bitte, ... BITTE! nicht wieder über irgendwelche Unterobjekte!

Guido.
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#25

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 09:20
Hallo,
Zitat von Guido Eisenbeis:
Nehmen wir das Beispiel von ganz am Anfang und gestalten es der Klarheit wegen noch ein wenig einfacher:

Delphi-Quellcode:
function GetFileIcon(AFileName: string): TIcon;
begin
  Result := TIcon.Create;
  Result.LoadFromFile(AFileName);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Icon aus Exe auslesen und Image zuweisen
  Image1.Picture.Graphic := GetFileIcon('C:\Test.ico');
end;
Wie willst du das mit dem "with try finally free end" lösen? Und bitte, ... BITTE! nicht wieder über irgendwelche Unterobjekte!
Das lässt sich natürlich nicht ohne eine Hilfsvariable erledigen.
Die einzige Möglichkeit wäre hier folgende:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Icon: TIcon;
begin
  // Icon aus Exe auslesen und Image zuweisen
  Icon := GetFileIcon('C:\Test.ico');
  try
    Image1.Picture.Graphic := Icon;
  finally
    Icon.Free;
  end;
end;
Etwas anderes macht ja with auch nicht, nur dass Du auf die Hilfsvariable nicht explizit zugreifen kannst. Das ist übrigens ein großer Nachteil dieses Konstrukts. Chrome hat das besser gelöst:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  with Icon := GetFileIcon('C:\Test.ico') do
  begin
    Image1.Picture.Graphic := Icon;
    Icon.Free;
  end;
end;
Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#26

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 09:37
Zitat von xaromz:
Das lässt sich natürlich nicht ohne eine Hilfsvariable erledigen.
Die einzige Möglichkeit wäre hier folgende:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Icon: TIcon;
begin
  // Icon aus Exe auslesen und Image zuweisen
  Icon := GetFileIcon('C:\Test.ico');
  try
    Image1.Picture.Graphic := Icon;
  finally
    Icon.Free;
  end;
end;
Wird da nicht gleichzeitig auch Image1.Picture.Graphic freigegeben?
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Benutzerbild von inherited
inherited

Registriert seit: 19. Dez 2005
Ort: Rosdorf
2.022 Beiträge
 
Turbo Delphi für Win32
 
#27

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 09:41
IMHO ja, besser wäre da "Assign"
Nikolai Wyderka

SWIM SWIM HUNGRY!
Neuer Blog: hier!
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#28

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 10:30
Hallo,

Zitat von Angel4585:
Wird da nicht gleichzeitig auch Image1.Picture.Graphic freigegeben?
Nein, intern wird beim Schreibzugriff auf die Eigenschaft Graphic eine neue TGraphic-Instanz angelegt, der dann mittels Assign() das übergebene Bild zugewiesen wird.

Zitat von inherited:
IMHO ja, besser wäre da "Assign"
Das kann ins Auge gehen, da die Eigenschaft Graphic durchaus den Wert NIL enthalten kann.

Zitat von xaromz:
Das lässt sich natürlich nicht ohne eine Hilfsvariable erledigen.
Als BDS-Nutzer könntest du das auch mit einer helper class erledigen:

Delphi-Quellcode:
type
  TObjectHelper = class helper for TObject
    function Instance: TObject;
  end;

function TObjectHelper.Instance;
begin
  Result := Self;
end;

procedure TForm1.Button1Click (Sender: TObject);
begin
  // Icon aus Exe auslesen und Image zuweisen
  with GetFileIcon('C:\Test.ico') do
  try
    Image1.Picture.Graphic := TIcon(Instance);
  finally
    Free;
  end;
end;
Die helper class könnte man noch in eine Bibliotheks-Unit auslagern und wiederverwenden. Die Lösung wirkt aber etwas unsauber und erreicht nicht die Eleganz des Chrome-Konstrukts. Letztlich spart sie nur etwas Schreibarbeit.

Gruß Hawkeye
  Mit Zitat antworten Zitat
IngoD7

Registriert seit: 16. Feb 2004
464 Beiträge
 
Delphi 7 Enterprise
 
#29

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 12:35
Hallo Guido,

Zitat von Guido Eisenbeis:
Eine(n) hab ich noch:

Zitat von IngoD7:
Natürlich immer fein mit Image1.Picture.Icon.ReleaseHandle; freigeben.
An welcher Stelle des Codes würdest du das aufrufen?
Wann immer ich das aktuell angezeigte Icon (das belegt ja Speicher) nicht mehr anzeigen möchte (und ja daher das Handle auch nicht mehr benötige). Das kann also auch sein, wenn ich Icon.Handle ein anderes Handle (also quasi ein anderes Icon) zuweise. Da würde ich vorher das alte Handle releasen. So steht's auch in der Online-Hilfe zu Icon.ReleaseHandle.

Zitat von Guido Eisenbeis:
Ich kann aber das Icon nicht freigeben, solange ich es in Image1 noch benötige. Muss man sich da noch bei Programmende drum kümmern, oder erfolgt dann eine Freigabe automatisch?
Das weiß ich leider nicht. Ich weiß nicht, wie Delphi bzw. ein Delphi-Compilat oder auch Windows selbst bei Programmende mit zuvor durch API-Funktionen belegten Speicherbereichen umgeht.

Mangels dieses Wissens würde ich es (sicherheitshalber) immer selbst freigeben - wie oben gesagt, wann immer ich dieses Icon nicht mehr brauche. Das kann auch (erst) bei Programmende sein.
  Mit Zitat antworten Zitat
Guido Eisenbeis

Registriert seit: 9. Apr 2006
389 Beiträge
 
Delphi 10.3 Rio
 
#30

Re: Funktionsrückgabe freigeben

  Alt 11. Mär 2007, 19:10
@Angel4585

Noch ein Wort zu meinem vorherigen Post: Als ich das geschrieben habe, war es schon spät und Guido war sehr, sehr müde!

Als ich das heute nochmal durchgelesen habe, klang das irgendwie ein wenig hart! Eigentlich wollte ich da noch ein paar Smilies einfügen, um das aufzulockern. Der Leser sieht man ja nicht, wie der Schreiber das meint. Deshalb hier noch die Klarstellung, dass das nicht bös oder sonstwie abweisend gemeint war!


@Ingo

Danke für Antwort!


@xaromz

Was ist Chrome? In Delphi geht dieses Konstrukt nicht.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Icon: TIcon;
begin
  with Icon := GetFileIcon('C:\Test.ico') do
  begin
    Image1.Picture.Graphic := Icon;
    Icon.Free;
  end;
end;
@Hawkeye

Zitat von Angel4585:
Wird da nicht gleichzeitig auch Image1.Picture.Graphic freigegeben?
Das hätte ich auch gedacht.

Zitat von Hawkeye219:
Nein, intern wird beim Schreibzugriff auf die Eigenschaft Graphic eine neue TGraphic-Instanz angelegt, der dann mittels Assign() das übergebene Bild zugewiesen wird.
Hier der "Aha!"-Effekt! Und wieder was dazugelernt!

Gruß,
Guido.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz