Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Methode "Free" selbst implementieren (Assembler-Problem?) (https://www.delphipraxis.net/40867-methode-free-selbst-implementieren-assembler-problem.html)

retnyg 22. Feb 2005 15:44

Re: Methode "Free" selbst implementieren (Assemble
 
dann halt so:
Delphi-Quellcode:
procedure dosomething;
begin
  mydestroyvariable := true;
end;

procedure TObject.Free(myparam:boolean); stdcall;
asm
        pop edx
        cmp edx, 1 
        jne @@weiter
        call dosomething
@@weiter:
        TEST   EAX,EAX
        JE     @@exit
        MOV    ECX,[EAX]
        CALL   dword ptr [ECX].vmtDestroy
@@exit:
end;

MaBuSE 22. Feb 2005 15:49

Re: Methode "Free" selbst implementieren (Assemble
 
Folgendes "einfaches" Beispiel sollte Dein Problem lösen:

Unit1.pas
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TMyObject = class;

  TMyObject = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
    MyRefCount: Integer;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    function GetMyObject: TMyObject;
    procedure FreeMyObject;
  end;

var
  MyObject: TMyObject;

implementation

{$R *.dfm}

{ TMyObject}

// Hier wird nur MyRefCount hochgezählt (auf 1 gesetzt)
constructor TMyObject.Create(AOwner: TComponent);
begin
  inherited;
  Inc(MyRefCount);
end;

// hiermit werden die Objekte freigegeben
procedure TMyObject.FreeMyObject;
begin
  if Self <> nil then
  begin
    Dec(MyRefCount);
    if MyRefCount < 1 then Self.Free;
  end;
end;

// hiermit wird eine Objektreferenz geholt
function TMyObject.GetMyObject: TMyObject;
begin
  if Self <> nil then
  begin
    Inc(MyRefCount);
    Result := Self;
  end
  else
  begin
    Result := nil;
  end;
end;

// Der Timer ist nur auf dem Form, damit man sieht wie viele Refs es gibt
procedure TMyObject.Timer1Timer(Sender: TObject);
begin
  Caption := IntToStr(MyRefCount);
end;

end.
Hier werden 3 wichtige Dinge implementiert:
  • Create wird überladen der der Referenzzähler auf 1 gesetzt
  • Mit GetMyObject wird das akive Object übergeben und der Referenzzähler um 1 erhöht
  • Mit FreeMyObject wird die aktive Referenz freigegeben und der Referenzzähler um 1 erniedrigt
Anwendung siehe Unit2:
Delphi-Quellcode:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

var a, b : TMyObject;

procedure TForm2.Button1Click(Sender: TObject);
begin
  MyObject := TMyObject.Create(self);
  MyObject.Show;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  a := MyObject.GetMyObject;
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
  b := MyObject.GetMyObject;
end;

procedure TForm2.Button4Click(Sender: TObject);
begin
  a.FreeMyObject;
  a := nil;
end;

procedure TForm2.Button5Click(Sender: TObject);
begin
  b.FreeMyObject;
  b := nil;
end;

procedure TForm2.Button6Click(Sender: TObject);
begin
  MyObject.FreeMyObject;
  MyObject := nil
end;

procedure TForm2.Button7Click(Sender: TObject);
begin
  Close;
end;

end.
Die Unit 2 ist ein leeres TForm mit 7 TButtons
  • Button1 = MyObject erzeugen und anzeigen
  • Buttin2 = MyObject wird A zugewiesen
  • Buttin3 = MyObject wird B zugewiesen
  • Buttin4 = A wird freigegeben
  • Buttin5 = B wird freigegeben
  • Buttin6 = MyObject wird freigegeben
  • Button7 = Programmende
Egal in welcher Reihenfolge freigegeben wird, verschwindet das Fenster TMyObject erst, wenn die letzte Referenz freigegeben wurde.

Das Ganze wird in die Project1.dpr eingebunden:
Delphi-Quellcode:
program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {MyObject},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.
Viel Spaß

[edit]
wichtig: Es muß natürlich erst der Button1 gedrückt werden, damit TMyObject.Create aufgerufen wird. ;-)
[/edit]

VizeTE 23. Feb 2005 08:14

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von MaBuSE
Egal in welcher Reihenfolge freigegeben wird, verschwindet das Fenster TMyObject erst, wenn die letzte Referenz freigegeben wurde.

Das ist ja mal ein ganz anderer Ansatz, sehr interessant. Da muß ich mal d'rüber nachdenken ob ich das auf meine Problemstellung anwenden kann. Aber auf jeden Fall erstmal vielen Dank für deine Mühe! :spin:

MaBuSE 23. Feb 2005 08:52

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von VizeTE
Zitat:

Zitat von MaBuSE
Egal in welcher Reihenfolge freigegeben wird, verschwindet das Fenster TMyObject erst, wenn die letzte Referenz freigegeben wurde.

Das ist ja mal ein ganz anderer Ansatz, sehr interessant. Da muß ich mal d'rüber nachdenken ob ich das auf meine Problemstellung anwenden kann. Aber auf jeden Fall erstmal vielen Dank für deine Mühe! :spin:

Das ist nur ein einfacher Ansatz. Das lässt sich natürlich auch noch beliebig ausbauen.

Bei .net gibt’s den GarbageCollector, der macht so was Ähnliches. (Nur viel komplizierter :mrgreen:)
Wenn es auf ein Objekt keine Referenz mehr gibt, dann wird es in die "Müllsammlung" gegeben und irgendwann später aus dem Speicher entfernt. Aber solange es mindestens eine Referenz gibt, bleibt es im Speicher.

jbg 23. Feb 2005 09:34

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von VizeTE
Wegen einem Free sieht man ja, wie gesagt, nicht extra in die Dokumentation.

Genau. Und was passiert wenn man dein Objekt in eine TObject Referenz steckt? Dann wird bei obj.Free das TObject.Free aufgerufen und nicht deine neue Version.

VizeTE 23. Feb 2005 11:36

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von jbg
Genau. Und was passiert wenn man dein Objekt in eine TObject Referenz steckt? Dann wird bei obj.Free das TObject.Free aufgerufen und nicht deine neue Version.

Probleme sehe ich dann nur wenn Delphi das an irgendeiner Stelle selbtständig macht. (Ich weiß nicht wann sowas passiert, gib mir doch mal bitte ein Beispiel [Meine Klasse ist von TList abgeleitet]).
Geht man davon aus, daß jemand das von Hand macht dann sollte man ja OOP vollständig vermeiden. Derjenige der sowas manuell macht sollte sich auch schlau machen welche Auswirkungen das hat, oder?
Wie würdest du denn das lösen?

maximov 23. Feb 2005 11:51

Re: Methode "Free" selbst implementieren (Assemble
 
Wenn dies alles dafür gedacht ist, objekte am leben zu erhalten, die noch referenziert werden, warum verwendest du dann nicht die automatisch COM-refCount geschichte? Du müsstest dann nur leider mit interface-refenren arbeiten.

VizeTE 23. Feb 2005 12:06

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von maximov
Wenn dies alles dafür gedacht ist, objekte am leben zu erhalten, die noch referenziert werden, warum verwendest du dann nicht die automatisch COM-refCount geschichte? Du müsstest dann nur leider mit interface-refenren arbeiten.

Nee, dafür war es nicht gedacht. Eigentlich wollte ich für Free einen Parameter übergeben mit dem entschieden wird ob Kind-Elemente ebenfalls freigegeben werden sollen. Ich wollte das nicht als Eigenschaft implementieren weil das für mich einfach eindeutiger erschien wenn es exakt ein Free gibt welches einen Parameter verlangt.

maximov 23. Feb 2005 15:24

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von VizeTE
Zitat:

Zitat von maximov
Wenn dies alles dafür gedacht ist, objekte am leben zu erhalten, die noch referenziert werden, warum verwendest du dann nicht die automatisch COM-refCount geschichte? Du müsstest dann nur leider mit interface-refenren arbeiten.

Nee, dafür war es nicht gedacht. Eigentlich wollte ich für Free einen Parameter übergeben mit dem entschieden wird ob Kind-Elemente ebenfalls freigegeben werden sollen. Ich wollte das nicht als Eigenschaft implementieren weil das für mich einfach eindeutiger erschien wenn es exakt ein Free gibt welches einen Parameter verlangt.

IMO macht es mehr sinn, das innerhalb der objekt-beziehungen die besitzansprüche genau geklärt sind und somit nur objekte freigegeben werden, die einem auch tatsächlich gehören. Diese lösung mit dem parameter erscheint mir mehr als unglücklich. Mir ist kein fall bekannt, bei dem ein delphi-priogrammierer gezwungen war einen ähnlichen weg zu gehen. IMO sind Free und Destroy unantastbar.

VizeTE 24. Feb 2005 08:15

Re: Methode "Free" selbst implementieren (Assemble
 
Zitat:

Zitat von maximov
IMO macht es mehr sinn, das innerhalb der objekt-beziehungen die besitzansprüche genau geklärt sind und somit nur objekte freigegeben werden, die einem auch tatsächlich gehören. Diese lösung mit dem parameter erscheint mir mehr als unglücklich. Mir ist kein fall bekannt, bei dem ein delphi-priogrammierer gezwungen war einen ähnlichen weg zu gehen. IMO sind Free und Destroy unantastbar.

Jaja, da habe ich mich ja schon überzeugen lassen. Nun bin ich am überlegen ob ich das halt doch vorher per Property mache (wie in TObjectList), versuche das mit dem RefCount umzusetzen oder vielleicht laß ich das Objekt wissen wem es gehört. Dann könnten die Listen nur die Eigenen freigeben. Das ist vielleicht die flexibelste Möglichkeit.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:57 Uhr.
Seite 3 von 5     123 45      

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