Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Objekte / Freigaben / Free / Nil (https://www.delphipraxis.net/176997-objekte-freigaben-free-nil.html)

Alex_ITA01 9. Okt 2013 14:25

Objekte / Freigaben / Free / Nil
 
Hallo zusammen,
ich habe folgendes Beispiel und eigentlich zwei Fragen dazu:

Delphi-Quellcode:
unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

Type
  TFreeObjList  = Class (TStringList)
    destructor Destroy; override;
  end;

  TMyOwnObject = class
  protected
  private
    Myfrm : TForm;
    function CheckA : boolean;
  public
    a          : SmallInt;
    b          : Double;
    c          : TDateTime;
    d          : AnsiString;
    e          : String[40];
    ObjInternList : TFreeObjList;

    function CheckB : Boolean;

    constructor Create;
    destructor Destroy; override;
  end;

type
  TForm4 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
    tmpObject : TMyOwnObject;
    MyObjList : TFreeObjList;
  public
    { Public-Deklarationen }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

{---------------------------------------------------------------------------}
{------------ TFreeObjList- Stringliste mit Freigabe aller Objekte ---------}
{---------------------------------------------------------------------------}
destructor TFreeObjList.Destroy;
Var
  i     : Integer;
  TmpObj : TObject;
begin
  for i:=0 to Count-1 do
  begin
    TmpObj := Objects[i];
    if Assigned(TmpObj) then
      FreeAndNil(TmpObj);
  end;
  Inherited Destroy;
end;
{---------------------------------------------------------------------------}
{ TMyOwnObject }
{---------------------------------------------------------------------------}
function TMyOwnObject.CheckA: boolean;
begin
  Result := A <> 0;
end;
{---------------------------------------------------------------------------}
function TMyOwnObject.CheckB: Boolean;
begin
  Result := B <> 0.0;
end;
{---------------------------------------------------------------------------}
constructor TMyOwnObject.Create;
begin
  Myfrm := TForm.Create(Application);
  ObjInternList := TFreeObjList.Create;

  a := 1;
  b := 2;
  c := Now;
  d := 'Hello';
  e := 'World';
end;
{---------------------------------------------------------------------------}
destructor TMyOwnObject.Destroy;
begin
  ObjInternList.Free;

  if Assigned(ObjInternList) then
    Sleep(0);

  inherited;
end;
{---------------------------------------------------------------------------}
procedure TForm4.FormCreate(Sender: TObject);
begin
  MyObjList := TFreeObjList.Create;
end;
{---------------------------------------------------------------------------}
procedure TForm4.FormDestroy(Sender: TObject);
var
  i   : Integer;
  aObj : TMyOwnObject;
begin
  MyObjList.Free;

  if Assigned(tmpObject) then
  begin
    if tmpObject.CheckA then
      Sleep(0);
    if Assigned(tmpObject.ObjInternList) then
      Sleep(0);
  end;

  if Assigned(MyObjList) then
  begin
    for i := 0 to MyObjList.Count - 1 do
    begin
      aObj := MyObjList.Objects[i] as TMyOwnObject;
      if Assigned(aObj) then
      begin
        if aObj.CheckA then
          Sleep(0);
        if aObj.CheckB then
          Sleep(0);
      end;
    end;
  end;
end;
{---------------------------------------------------------------------------}
procedure TForm4.Button1Click(Sender: TObject);
var
  aObj : TMyOwnObject;
begin
  if Assigned(MyObjList) then
  begin
    aObj := TMyOwnObject.Create;
    MyObjList.AddObject(TimeToStr(aObj.c), aObj);
  end;
end;
{---------------------------------------------------------------------------}
procedure TForm4.Button2Click(Sender: TObject);
begin
  if Assigned(MyObjList) and (MyObjList.Count > 0) then
  begin
    tmpObject := MyObjList.Objects[0] as TMyOwnObject;
    if Assigned(tmpObject) then
      Sleep(0);
  end;
end;
{---------------------------------------------------------------------------}
end.
Die Reihenfolge ist erst den Button1 zu betätigen, dann den Button2.
Da wird sich auf eine gloable Variable der Inhalt des ersten Objektes geholt.

Wenn ich dann die Anwendung beende, passieren eigentlich zwei Dinge:
1) Das Objekt ist immernoch vorhanden und es kann drauf zugegriffen werden obwohl die Liste alle ihre Objekte durchgegangen ist und FreeAndNil gesagt hat
Delphi-Quellcode:
if Assigned(tmpObject) then

2) Vor dem Aufruf von "MyObjList.Free;" enthält das gloable Objekt noch den vollständigen Inhalt (inkl. des AnsiStrings "Hello"). Nach dem Aufruf von "MyObjList.Free;" ist bei dem globalen Objekt bis auf dem AnsiString noch alle vorhanden. Der AnsiString ist auf einmal nicht mehr "Hello" sondern ein Leerstring. Ich hätte doch dann jetzt erwartet, dass entweder alles weg ist (=Nil) oder noch alles da ist.

Könnt ihr mich hier mal bitte aufklären?
Umgebung = XE4

Gruß

Uwe Raabe 9. Okt 2013 14:42

AW: Objekte / Freigaben / Free / Nil
 
Delphi-Quellcode:
   
    TmpObj := Objects[i];
    if Assigned(TmpObj) then
      FreeAndNil(TmpObj);
Mal abgesehen davon, daß das if Assigned überflüssig ist, setzt FreeAndNil nur TmpObj auf nil, nicht aber Objects[I].

Strings haben eine implizite Referenzzählung und der Compiler behandelt sie bei Klassen und Records anders als andere Typen.

baumina 9. Okt 2013 14:51

AW: Objekte / Freigaben / Free / Nil
 
Ich würde im Destroy lieber rückwärts freigeben, also statt for i:=0 to Count-1 lieber for i:=Count-1 downto 0.

generic 9. Okt 2013 14:54

AW: Objekte / Freigaben / Free / Nil
 
Delphi-Quellcode:
 TFreeObjList = Class (TStringList)
Du kannst auch die TObjectList nutzen. Diese kann Objekte auch selbst freigeben.

Alex_ITA01 9. Okt 2013 14:59

AW: Objekte / Freigaben / Free / Nil
 
@baumina:
Zitat:

Ich würde im Destroy lieber rückwärts freigeben, also statt for i:=0 to Count-1 lieber for i:=Count-1 downto 0.
Darf ich fragen warum?

@Uwe Raabe:
Was müsste ich denn machen, um das Object[i] als solches auch freizugeben und auf Nil zu setzen?

Gruß

DeddyH 9. Okt 2013 15:01

AW: Objekte / Freigaben / Free / Nil
 
Delphi-Quellcode:
FreeAndNil(Objects[i]);
Wobei mir nicht klar ist, wozu genilt werden soll, wenn die Liste danach eh futsch ist.

mkinzler 9. Okt 2013 15:02

AW: Objekte / Freigaben / Free / Nil
 
Delphi-Quellcode:
Darf ich fragen warum?
weil sich u.U. durch Löschen der Index ändern könnte

Union 9. Okt 2013 15:02

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231423)
@baumina:
Zitat:

Ich würde im Destroy lieber rückwärts freigeben, also statt for i:=0 to Count-1 lieber for i:=Count-1 downto 0.
Darf ich fragen warum?

@Uwe Raabe:
Was müsste ich denn machen, um das Object[i] als solches auch freizugeben und auf Nil zu setzen?

Gruß

Weil die Liste jedesmal schrumpft und Du die Anzahl der Elemnte überschreitest. Also entweder mit
Delphi-Quellcode:
for ... downto
oder mit
Delphi-Quellcode:
while count > 0

Namenloser 9. Okt 2013 15:03

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231423)
@baumina:
Zitat:

Ich würde im Destroy lieber rückwärts freigeben, also statt for i:=0 to Count-1 lieber for i:=Count-1 downto 0.
Darf ich fragen warum?

Vielleicht kann es nicht schaden, sich das zur Gewohnheit zu machen, denn wenn man z.B. statt FreeAndNil Delete aufruft, bekommt man sonst Probleme. Aber eigentlich ist es hier unnötig...

Edit: Eine andere Sache, die mir an dem Code hier auffällt, ist allerdings die völlige Sinnlosigkeit von FreeAndNil. Die Prozedur gibt dir hier nur falsche Sicherheit, denn alles was sie tut, ist, die lokale Variable auf nil zu setzen. In der Liste selbst ändert sich nichts. Ach das Prüfen mit Assigned ist daher völlig sinnlos und erschwert höchstens die Fehlersuche.

DeddyH 9. Okt 2013 15:04

AW: Objekte / Freigaben / Free / Nil
 
Seit wann schrumpft eine TStringlist, wenn ich deren Objekte freigebe?

Der schöne Günther 9. Okt 2013 15:17

AW: Objekte / Freigaben / Free / Nil
 
In dem Fall vielleicht nicht. Aber angenommen, man iteriert rein über den Index über eine Liste und
Delphi-Quellcode:
meineListe.EntferneEintragMitNummer(34)
lässt nun alles nach Stelle 34 aufrücken? Dann doch wohl.

baumina 9. Okt 2013 15:18

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231423)
@baumina:
Zitat:

Ich würde im Destroy lieber rückwärts freigeben, also statt for i:=0 to Count-1 lieber for i:=Count-1 downto 0.
Darf ich fragen warum?

Hast recht, müsste bei einer StringList egal sein wie rum, da sich ja die Größe der Liste beim Object.Free nicht verändert.

EDIT : Aber solltest du im Destroy nicht einen TypeCast auf TMyOwnObject machen? FreeAndNil(TMyOwnObject(Objects[i]))

Alex_ITA01 9. Okt 2013 15:22

AW: Objekte / Freigaben / Free / Nil
 
Ok, danke für die Hinweise.
Mich interessiert natürlich jetzt noch das Thema mit dem FreeAndNil(tmpObj) und dem Object was noch später verfügbar ist.

Bzw. Wie gibt man die Objecte innerhalb der Liste denn richtig frei?

Gruß

DeddyH 9. Okt 2013 15:26

AW: Objekte / Freigaben / Free / Nil
 
Um den Knoten aufzulösen: Löschen mehrerer Elemente in einer Liste sollte man bei einer For-Schleife rückwärts machen, um Indexfehler zu vermeiden, da die Schleifenanzahl dort nur einmalig ermittelt wird. Alternativ kann man auch eine While-Schleife benutzen:
Delphi-Quellcode:
while Liste.Count > 0 do
  Liste.Delete(0);
Beim Ändern von Elementen ist es im Normalfall egal, ob man das vorwärts oder rückwärts macht, es sei denn, die Liste löscht in bestimmten Fällen selbstständig Einträge. Sofern man sich nicht sicher ist: rückwärts durchlaufen, dann kann man nicht viel falsch machen.

Uwe Raabe 9. Okt 2013 15:27

AW: Objekte / Freigaben / Free / Nil
 
Du kannst dir bei XE4 die Ableitung von TStringList sparen, wenn du deren property OwnsObjects auf true setzt. Damit gibt die Liste beim Löschen von Elementen und somit auch im eigenen Destroy auch die Objects frei.

Namenloser 9. Okt 2013 15:30

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von DeddyH (Beitrag 1231440)
Alternativ kann man auch eine While-Schleife benutzen:
Delphi-Quellcode:
while Liste.Count > 0 do
  Liste.Delete(0);

Hat dann allerdings quadratische Laufzeit.

Alex_ITA01 9. Okt 2013 15:35

AW: Objekte / Freigaben / Free / Nil
 
Ich muss allerdings TStringList ableiten, da ich noch ein paar andere Funktionen nachgepflegt habe in meiner abgeleitetn TStringList.
Reicht es dann, wenn ich in meiner abgeleiteten Liste das OwnObjects auf True setze?

Gruß

Uwe Raabe 9. Okt 2013 15:38

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231445)
Ich muss allerdings TStringList ableiten, da ich noch ein paar andere Funktionen nachgepflegt habe in meiner abgeleitetn TStringList.
Reicht es dann, wenn ich in meiner abgeleiteten Liste das OwnObjects auf True setze?

Ja.

Alex_ITA01 9. Okt 2013 15:47

AW: Objekte / Freigaben / Free / Nil
 
Ich habe jetzt folgendes geändert aber das globale Objekt ist immernoch verfügbar:

Delphi-Quellcode:
destructor TFreeObjList.Destroy;
Var
  i     : Integer;
  TmpObj : TObject;
begin
  {for i:=0 to Count-1 do
  begin
    TmpObj := Objects[i];
    if Assigned(TmpObj) then
      FreeAndNil(TmpObj);
  end; }

  Inherited Destroy;
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
  MyObjList := TFreeObjList.Create;
  MyObjList.OwnsObjects := True;
end;
Also hat sich eigentlich nichts dadurch geändert.
Was habe ich denn falsch gemacht bzw. falsch verstanden?

Gruß

Uwe Raabe 9. Okt 2013 15:59

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231447)
Ich habe jetzt folgendes geändert aber das globale Objekt ist immernoch verfügbar:

Delphi-Quellcode:
procedure TForm4.FormCreate(Sender: TObject);
begin
  MyObjList := TFreeObjList.Create;
  MyObjList.OwnsObjects := True;
end;

Und wo gibst du MyObjList frei? Ich hätte jetzt im FormDestroy ein MyObjList.Free oder ein entsprechendes FreeAndNil erwartet.

Namenloser 9. Okt 2013 15:59

AW: Objekte / Freigaben / Free / Nil
 
Free bzw. Destroy gibt nur den Speicherbereich wieder frei – das sagt nur dem Speichermanager, dass er den Speicherplatz neu vergeben darf. Der Speicher wird aber nicht überschrieben – wozu auch, normalerweise sollte da ja niemand mehr drauf zugreifen.

Es kann also schon sein, dass nach einer Freigabe die Daten des Objektes noch an der Stelle im Speicher stehen, obwohl das Objekt nicht mehr existiert. Darauf kann man sich aber nicht verlassen.

Blup 9. Okt 2013 16:34

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von baumina (Beitrag 1231436)
EDIT : Aber solltest du im Destroy nicht einen TypeCast auf TMyOwnObject machen? FreeAndNil(TMyOwnObject(Objects[i]))

Das ist für den Aufruf des richtigen Destruktors nicht notwendig. Destroy ist schon in der Basisklasse TObject virtuell deklariert.
Jede Klasse muss Destroy, wenn erforderlich, in geeigneter Weise überschrieben, um die Instanz vollständig freizugeben.

Alex_ITA01 9. Okt 2013 20:10

AW: Objekte / Freigaben / Free / Nil
 
@Uwe: Ich habe ja nur den Quelltext an den beiden besagten Stellen angepasst. Siehe also mein Beispiel im ersten Post, dort steht ja im FormDestroy "MyObjList.Free;".
Trotzdem kann ich nach der besagten Änderung (OwnObjects=True) immernoch im FormDestroy nach dem "MyObjList.Free;" folgendes abfragen/aufrufen:

Delphi-Quellcode:
if Assigned(tmpObject) then
  begin
    if tmpObject.CheckA then
      Sleep(0);
    if Assigned(tmpObject.ObjInternList) then
      Sleep(0);
  end;
Das ist ja nur eine Minianwendung wo es recht übersichtlich ist. Wie kann man denn ganz sicher die Objekte freigeben und falls jemand anderes (vielleicht ein parallel laufender Thread) diese auf Gültigkeit abfragt auch wirklich feststellen, dass man noch drauf zu greifen kann?!

Gruß

jaenicke 9. Okt 2013 20:30

AW: Objekte / Freigaben / Free / Nil
 
Nebenbei hat eine TStringList bei aktuellen Delphiversionen die Eigenschaft OwnsObjects.

Namenloser 9. Okt 2013 20:43

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231481)
Das ist ja nur eine Minianwendung wo es recht übersichtlich ist. Wie kann man denn ganz sicher die Objekte freigeben und falls jemand anderes (vielleicht ein parallel laufender Thread) diese auf Gültigkeit abfragt auch wirklich feststellen, dass man noch drauf zu greifen kann?!

Geht nicht. Musst du anders lösen, z.B. über ein Observer-Pattern.

Und Multi-Thread ist noch mal eine Sache für sich...

Alex_ITA01 9. Okt 2013 21:20

AW: Objekte / Freigaben / Free / Nil
 
@jaenicke: Das war ja auch der Vorschlag von Uwe Raabe aber das Endergebnis ist ja das gleiche. Ich kann nicht erkennen, ob das Objekt noch da ist oder nicht.

Sowohl in meinem Beispiel in Post 1 als auch die Variante mit OwnsObjects wird mir mit ReportOnMemoryLeaks auch kein Speicherleck abgezeigt.
Ist ja schön wenn das auch so ist aber ich verstehe nur nicht, warum ich auf alle Eigenschaften und Variablen des Objekts zugreifen kann obwohl es eigentlich freigegeben wurde.
Gibt es keine Variante, dass Objekt so freizugeben, dass eine
Delphi-Quellcode:
if Assigned
Abfrage dann auch wirklich "False" liefert?

Gruß

Uwe Raabe 9. Okt 2013 21:41

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231486)
Gibt es keine Variante, dass Objekt so freizugeben, dass eine
Delphi-Quellcode:
if Assigned
Abfrage dann auch wirklich "False" liefert?

Solange du die besagte Variable nicht selbst auf nil setzt, nein. Dein Problem ist, daß mehrere Variablen auf dasselbe Objekt verweisen. Wird dieses Objekt freigegeben, zeigen alle diese Variablen auf einen ungültigen Speicherbereich. Das kannst du ohne erheblichen Aufwand nicht vermeiden. Schon gar nicht im Multithread-Bereich.

stahli 9. Okt 2013 21:41

AW: Objekte / Freigaben / Free / Nil
 
Das Problem ist nicht so einfach zu lösen.

Hier mal ein paar ältere Diskussionen dazu:
http://www.delphipraxis.net/166899-i...eferenzen.html
http://www.delphipraxis.net/159095-r...e-objekte.html

Alex_ITA01 9. Okt 2013 21:43

AW: Objekte / Freigaben / Free / Nil
 
Ok danke für die Info. Wo wäre denn die richtige Stelle zum Nil setzen, wenn ich es selber machen muss @Uwe?

Gruß

Uwe Raabe 9. Okt 2013 23:26

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Alex_ITA01 (Beitrag 1231492)
Ok danke für die Info. Wo wäre denn die richtige Stelle zum Nil setzen, wenn ich es selber machen muss @Uwe?

Nach deinem gezeigten Code zu urteilen, wäre folgende Code-Sequenz im FormDestroy korrekt:

Delphi-Quellcode:
procedure TForm4.FormDestroy(Sender: TObject);
begin
  tmpObject := nil;
  MyObjList.Free;
  MyObjList := nil;
end;

Die beiden if-Anweisungen würden demnach immer fehlschlagen und der dahinter liegende Code kann somit eliminiert werden. Solange die beiden Variablen nicht noch anderswo verwendet werden, braucht man sie dann aber auch nicht auf nil setzen. Damit reduziert sich das FormDestroy auf ein simples
Delphi-Quellcode:
MyObjList.Free;


Ich vermute aber, daß dein eigentlicher Code etwas ganz anderes macht. Dazu kann ich so natürlich nichts sagen.

Thom 10. Okt 2013 01:45

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von stahli (Beitrag 1231491)
Das Problem ist nicht so einfach zu lösen.

Hier mal ein paar ältere Diskussionen dazu:
http://www.delphipraxis.net/166899-i...eferenzen.html

Wie die Zeit vergeht... :roll:
Auf den diesjährigen Delphi-Tagen hatte ich dazu übrigens die Funktionsweise live im Debugger demonstriert. :-D
Es funktioniert also - wenn auch (momentan) nur unter Windows, da dazu intern Assemblerfunktionen verwendet werden.

jaenicke 10. Okt 2013 06:35

AW: Objekte / Freigaben / Free / Nil
 
In den meisten Anwendungsfällen sind in so einem Fall aber eher Interfaces passend. Dann braucht man sich nicht darum zu kümmern und das Objekt wird freigegeben, wenn es von keiner Seite mehr benutzt wird. Umgekehrt hat man es aber auch überall noch, auch wenn es in der ursprünglichen Liste schon weg ist.

Alex_ITA01 10. Okt 2013 07:32

AW: Objekte / Freigaben / Free / Nil
 
Danke für die zahlreichen Hinweise.
Ich habe nur noch zwei letzte Fragen ;-)

Aktuell habe ich die Variante mit den OwnsObjects aktiv und im FormDestroy rufe ich zur Zeit nur "FreeAndNil(MyObjList);" auf. Ich habe jetzt ja gelernt, dass dann das globale Objekt "tmpObject" noch vorhanden ist aber auf ein ungültigen Speicherbereich zeigt.

1) Woher weiß der Speichermanager eigentlich, dass diese Speicheradresse "ungültig" ist? Gibt es da irgendein Flag dafür?
2) Das das "if Assigned(tmpObject) then" weiterhin nach "FreeAndNil(MyObjList);" im FormDestroy funktioniert, habe ich verstanden aber warum crasht das Programm nicht, wenn ich dann auch auf die Inhalte und Funktionen von "tmpObject" zugreife nach der "if Assigned(tmpObject) then"-Abfrage?

Gruß

stahli 10. Okt 2013 08:26

AW: Objekte / Freigaben / Free / Nil
 
Wenn Du ein Objekt freigibst wird nur der Speicherbereich als verfügbar definiert.

Wenn Du jetzt noch darauf zugreifst und der Speicher noch nicht überschreiben wurde, dann kann das noch gut gehen.
Es kann aber auch sein, dass es in unvorhergesehener Form knallt, wenn die dort stehenden Binärdaten schon (teilweise) überschreiben wurde.


In meinem aktuellen Framework habe ich übrigens folgende Lösung:

In der Datanschicht sammle ich alle erzeugten Objekte in einer sortiereten Liste.
Diese fordere ich dann zur Laufzeit anhand einer Id an. Durch Binary Search geht das wirklich schnell.
Wurde ein Objekt bereits aufgelöst, gibt die Anfrage nil zurück.
Man muss dann halt immer wieder die Objekte "abfordern".

Die Objekte müssen dafür dann auch speziell angepasst sein.
So funktioniert das gut, aber halt nur in einem festgelegten Rahmen.

Delphi-Quellcode:
function TssIO_Custom.GetObject(Id: TssId): TssObject;
var
  Index: Integer;
  ssObj: TssObject;
begin
  Result := nil;
  ssObj := TssObject.Create(nil, Id, True);
  if ssObjectList.BinarySearch(ssObj, Index) then
    Result := ssObjectList[Index];
  FreeAndNil(ssObj);
end;

procedure TssIO_Custom.RegisterObject(ssObj: TssObject);
var
  Index: Integer;
begin
  if not Assigned(ssObj) then
    Exit;
  if ssObj.HideMode then
    Exit;
  if not ssObjectList.BinarySearch(ssObj, Index) then
    ssObjectList.Insert(Index, ssObj);
end;

procedure TssIO_Custom.UnregisterObject(ssObj: TssObject);
begin
  if not Assigned(ssObj) then
    Exit;
  if ssObj.HideMode then
    Exit;
  ssObjectList.Extract(ssObj);
end;

Eine Compilerlösung, Referenzen auf aufgelöste Objekte automatisch zu nilen ist wohl nicht in Aussicht.

jaenicke 10. Okt 2013 12:05

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von stahli (Beitrag 1231518)
Eine Compilerlösung, Referenzen auf aufgelöste Objekte automatisch zu nilen ist wohl nicht in Aussicht.

Weil es in 99,9% der Fälle keinen Sinn macht, deshalb fände ich es auch nicht gut, wenn dafür Entwicklung betrieben wird. Entweder braucht man die Objekte auch nach der Freigabe an anderer Stelle, dann kann man Interfaces nutzen oder man braucht sie nicht, dann kann man Objektreferenzen nutzen, sollte sie aber auch nicht an Stellen zwischenspeichern, bei denen unklar ist, ob sie dem Scope entsprechen.

Eine andere Möglichkeit wäre ein Kapselinterface, das einfach nur den Zeiger auf das Objekt enthält, der für die explizite Freigabe schlicht auf nil gesetzt wird. Dann kann man von überall über dieses Interface jederzeit prüfen, ob die Freigabe bereits erfolgt ist.

Trotzdem halte ich echte Interfaces für die bessere Lösung für derlei Probleme, von ARC im mobile Compiler mal abgesehen. Solche Tricksereien um nur ja bei Objektreferenzen bleiben zu können, wenn sie eigentlich schlicht nicht zum aktuellen Anwendungsfall passen, empfinde ich nicht als saubere Lösung.

stahli 10. Okt 2013 12:35

AW: Objekte / Freigaben / Free / Nil
 
Es gibt natürlich Gründe dafür, dass es so ist wie es ist und es gibt Alternativen mit jeweils Vor- und Nachteilen.

Aber eines kann man sicher feststellen:

Neulinge (im Delphi) werden immer davon ausgehen, dass Variablen, die auf ein Objekt zeigen, nach dessen Auflösung "leer" sind.

Man kann mit der Zeit lernen, dass das nicht so ist. Aber dem Mißverständnis werden nahezu alle Delphi-Neulinge auf den Leim gehen.

Insofern fände ich eine Compiler-Magie (oder wenigstens eine optionale Standard-Problemlösung) schon interessant. Alles andere sind mehr oder wenige aufwendige und mit Nachteilen verbundene Notlösungen.
Aber ich sehe ein, dass eine automatische Lösung nicht unproblematisch zu realisieren wäre.

Furtbichler 10. Okt 2013 12:46

AW: Objekte / Freigaben / Free / Nil
 
Grauenvoll, wenn der Compiler versucht, für mich mitzudenken. Das gab es mal bei VB und die Ergebnisse waren chaotisch. Wenn Variableninhalten sich auf einmal verändern, kann das nicht gut gehen.

Wenn mehr als ein Instanzenzeiger auf ein Objekt existiert, dann dürfte es sich um einen Designfehler handeln. Würde man einen Provider zwischenschalten, gäbe es die Probleme nicht: Der Provider meldet "is weg" oder instanziiert per lazy load eine neue Instanz.

Daher ist es müßig (imho) sich darüber Gedanken zu machen, ob der Compiler diesen Lapsus reparieren soll. Na, ginge schon. Aber wenn man damit anfängt, dann müsste man auch gleich vergessene Freigaben, Ressourcenschutzblöcke usw. vom Compiler 'reparieren' lassen.

Will hier keinem zu nahe treten, aber bitte bitte, nicht noch mehr Magic.

jaenicke 10. Okt 2013 12:47

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von stahli (Beitrag 1231592)
Insofern fände ich eine Compiler-Magie (oder wenigstens eine optionale Standard-Problemlösung) schon interessant.

Was ja in Zukunft mit ARC passiert, und das wird ja vermutlich auch für Win32 irgendwann existieren.

stahli 10. Okt 2013 12:57

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von Furtbichler (Beitrag 1231596)
Will hier keinem zu nahe treten, aber bitte bitte, nicht noch mehr Magic.

Du verkennst halt, dass nicht alle (Anfänger- und Hobby-)Programmierer auf Deinem Kenntnisstand sind. Das Problem und die Hintergründe werden erst die fortgeschritteneren durchschauen.

mkinzler 10. Okt 2013 13:07

AW: Objekte / Freigaben / Free / Nil
 
Zitat:

Zitat von stahli (Beitrag 1231601)
Zitat:

Zitat von Furtbichler (Beitrag 1231596)
Will hier keinem zu nahe treten, aber bitte bitte, nicht noch mehr Magic.

Du verkennst halt, dass nicht alle (Anfänger- und Hobby-)Programmierer auf Deinem Kenntnisstand sind. Das Problem und die Hintergründe werden erst die fortgeschritteneren durchschauen.

(Objekt-)Pascal (Delphi) hat aber schon lang den Status einer Lehrsprache verlassen, was Pascal (Wirth) ursprünglich ja mal war.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 Uhr.
Seite 1 von 2  1 2      

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