AGB  ·  Datenschutz  ·  Impressum  







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

Referenz Verwaltung

Ein Thema von Jonas Shinaniganz · begonnen am 21. Jun 2012 · letzter Beitrag vom 22. Jun 2012
Antwort Antwort
Benutzerbild von Jonas Shinaniganz
Jonas Shinaniganz

Registriert seit: 30. Aug 2011
249 Beiträge
 
Delphi XE5 Ultimate
 
#1

Referenz Verwaltung

  Alt 21. Jun 2012, 15:48
Hi Ihr Guten!

Es geht um Referenzen(Pointer) auf Instanzen die noch auf die Instanzen zeigen wenn die Instanzen schon freigegeben sind. (Der Speicher freigegeben ist)

Habe warscheinlich ein grundsätzliches Problem zu lösen. Ich lass am besten mal den Code sprechen, der sagt mehr als Worte und wenn Ich hier lange rede dann meißt eh nur um meinen Kopf und Kragen.

Delphi-Quellcode:

//type
  
TMeinObject = class(TObject)
public
  VarX : TMeinObject;
end;

KlasseA : TMeinObject;
KlasseB : TMeinObject;

//implmnt...

KlasseA := TKLasseA.Create;
KlasseB := TKLasseB.Create;

KlasseB.VarX := KlasseA;
KlasseA.VarX := KlasseB;

FreeAndNil(KlasseA);

if (Assigned(KlasseB.VarX)) then
begin
  ShowMessage('It is assigned... this did not help you sir.');
end;
Und klar kann ich so nicht herrausfinden ob da noch Zugriffsrechte bestehen weil die Referenz ja bloß ein ahnungsloser Pointer ist... KlasseB.VarX möchte doch bitte NIL sein. Deswegen:

Delphi-Quellcode:
TMeinObject = class(TObject)
public
  VarX : TMeinObject;
  ReferenzListe : TList;
  procedure FreeNotification(Sender : TObject);
  constructor Create;
  destructor Destroy; override;
end;

var
  KlasseA : TMeinObject;
  KlasseB : TMeinObject;

implementation

{$R *.dfm}

procedure wayne...
begin
  KlasseA := TKLasseA.Create;
  KlasseB := TKLasseB.Create;

  KlasseB.VarX := KlasseA;
  KlasseA.ReferenzListe.Add(KlasseB);

  KlasseA.VarX := KlasseB;
  KlasseB.ReferenzListe.Add(KlasseA);

  FreeAndNil(KlasseA);

  if (Assigned(KlasseB.VarX)) then
  begin
    ShowMessage('It is assigned... this did not help you sir.');
  end;

end;


constructor TMeinObject.Create;
begin
  ReferenzListe := TList.Create;
end;


destructor TMeinObject.Destroy;
var
  I: Integer;
begin
  // Referenzlisten Einträge Nillen
  for I := 0 to ReferenzListe.Count - 1 do
  begin
    TMeinObject(ReferenzListe[I]).FreeNotification(Self);
  end;
  ReferenzListe.Free;
  inherited;
end;


procedure TMeinObject.FreeNotification(Sender: TObject);
begin
  if Sender = VarX then
    VarX := nil;
end;

end.
Damit das jetzt alles brav implementiert wird und alle Klassen von denen Ich auch Referenzen erzeuge Ihre Referenzen selbst verwalten hatte Ich jetzt vor ein IInterface zu verwenden, das habe ich aber noch nie verwendet.

Delphi-Quellcode:
unit ReferenzVerwaltungsInterface;

interface

type
  IReferenceManager = interface(IInterface)

  end;

implementation

end.
Bevor Ich jetzt anfange zu Programmieren wollte Ich noch mal hier nachfragen ob es üblich ist so mit dem Problem umzugehen oder ob es etwas viel besseres / cooleres gibt wie man jetzt am besten einen solchen Referenzmanager aufbaut.

Grüße.
Die Leiter der Entwicklungsabteilung dreht total am Mausrad!
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.989 Beiträge
 
Delphi 12 Athens
 
#2

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 16:20
Wenn du Objekte an mehreren Stellen referenzierst, sind Interfaces eine gute Möglichkeit das zu lösen.

Dafür muss man natürlich dafür sorgen, dass die durch die Interfaces gekapselten Objekte nicht von anderen Sachen abhängig sind, die es dann nicht mehr gibt. Dieses Problem kann es bei der Mischung von Objektreferenzen und Interfaces relativ schnell geben.

An der Stelle verweise ich einmal auf das Delphi Spring Framework. Dazu gibt es auch viele Artikel wie diesen.
Ich persönlich kann den Ideen in der Ausprägung zwar nicht ganz so viel abgewinnen, weil sie mir zu weit gehen, aber andere finden das so gut, dass ich es dennoch erwähne. Was du davon hältst findest du am besten selbst heraus.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 16:38
Was du da vorhast ist so etwas wie die Vorstufe zu einer Garbage Collection.
Ich meine man sollte das entweder richtig oder gar nicht machen.
Im Falle von Delphi, das keinen Garbage Collector besitzt, würde ich auf solche Tricks wie Smart Pointer komplett verzichten.

Stattdessen benötigt man eine bestimmte (geistige) Einstellung, wie man mit Objekten oder Resourcen ganz allgemein umzugehen hat.
Wann immer ein Objekt erzeugt wird entsteht auch eine Verpflichtung das Objekt später wieder mit Free freizugeben.
So nach dem Motto: "Wer das Essen bestellt hat muss nachher auch abspülen"
Wenn in einem Formular ein Objekt erzeugt wird, dann hat das Formular den Besitz (Ownership) übernommen und damit auch die Verpflichtung sich um das Objekt zu kümmern.

Es ist aber auch möglich, diese Verpflichtung gezielt abzutreten.
Delphi-Quellcode:
var
  list : TObjectList;
  x : TMeineKlasse;
begin
  list := TObjectList.Create({OwnsObjects=}True);
  x := TMeineKlasse.Create;
  list.Add(x); // TObjectList sorgt für die spätere Freigabe von x
Bei Komponenten tritt diese Abgabe der Verantwortung bzw. Ownership ganz explizit zu Tage.
Man gibt im Konstruktor einfach den Owner an und der Owner wird sich schon um die Freigabe kümmern.

Jetzt ist eine Sache noch ganz wichtig
Keine globalen Objekt-Variablen verwenden!
Bei globalen Variablen hat niemand die Verantwortung übernommen; daher kommen die Probleme bei der Freigabe.
Wenn du alle deine globalen Variablen eliminierst, werden auch deine Probleme mit der Freigabe verschwinden.
Andreas
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#4

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 16:55
Im Falle von Delphi, [...], würde ich auf solche Tricks wie Smart Pointer komplett verzichten.
Weshalb verzichten? Und wieso ist das ein "Trick"? Ohne gegenseitige Benachrichtigung bei Freigabe von Objekten würde die ganze VCL nicht funktionieren...

Jetzt ist eine Sache noch ganz wichtig
Keine globalen Objekt-Variablen verwenden!
Bei globalen Variablen hat niemand die Verantwortung übernommen; daher kommen die Probleme bei der Freigabe.
Ganz einfach:
Delphi-Quellcode:
finalization
  MeinGlobalesObjekt.Free;
end.
Wo ist das Problem?
Thomas Nitzschke
Google Maps mit Delphi
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 17:16
Im Falle von Delphi, [...], würde ich auf solche Tricks wie Smart Pointer komplett verzichten.
Weshalb verzichten? Und wieso ist das ein "Trick"? Ohne gegenseitige Benachrichtigung bei Freigabe von Objekten würde die ganze VCL nicht funktionieren...
Die VCL verwendet keine Tricks sondern nur den etablierten Weg über Komponenten.

DAS hier ist ein Trick (in dem die Referenzzählung eines Interface ausgenützt wird):
Delphi-Quellcode:
unit UAutoRelease;

interface

{**************************************************************************
* NAME:    AutoRelease
* DESC:    Gibt das übergebene Objekt automatisch beim Verlassen der
*          aktuellen Funktion frei.
* PARAMS:  obj: TObject
* RESULT:  IUnknown
*
* Hilfsfunktion, um Objekte automatisch beim Verlassen der aktuellen
* Funktion freizugeben.
* Damit kann man sich manche try .. finally Blöcke sparen.
* Beispiel:
*    procedure xyz;
*    var sl: TStringList;
*      t : IUnknown;
*    begin
*      sl := TStringList.Create;
*      t := AutoRelease(sl);
*      sl.LoadFromFile('c:\autoexec.bat');
*      ...
*      // sl.Free wird nicht mehr benötigt!!!
*    end;
*************************************************************************}

function AutoRelease(obj: TObject): IUnknown;

implementation

type
   TAutoReleaseObject = class(TInterfacedObject, IUnknown)
   private
      FObject: TObject;
   public
      constructor Create(obj: TObject);
      destructor Destroy; override;
   end;

constructor TAutoReleaseObject.Create(obj: TObject);
begin
   inherited Create;
   FObject := obj;
end;

destructor TAutoReleaseObject.Destroy;
begin
   FObject.Free;
   inherited;
end;

function AutoRelease(obj: TObject): IUnknown;
begin
   Result := TAutoReleaseObject.Create(obj);
end;

end.
Delphi-Quellcode:
finalization
  MeinGlobalesObjekt.Free;
end.
Wo ist das Problem?
Das Problem ist, dass man globale Objekte vermeiden sollte wann immer es möglich ist.
Manchmal lässt es sich nicht vermeiden ein Objekt global anzulegen, aber jedes globale Objekt erzeugt auch Probleme wie schlechte Testbarkeit.
Wenn Projekte an Umfang zunehmen und Hunderte von Units haben ist jedes globale Objekt eine technische Schuld für die man "Zinsen" bezahlen muss.
Andreas

Geändert von shmia (21. Jun 2012 um 17:21 Uhr)
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#6

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 17:30
Die VCL verwendet keine Tricks sondern nur den etablierten Weg über Komponenten.
Eben. Und eine Komponente ist kein Objekt? Du hast mir also meine Frage noch nicht beantwortet: Weshalb soll man "Smart Pointer", "Smart Interfaces" oder wie immer solche Dinge auch genannt werden, nicht verwenden? Weil sie nicht "etabliert" sind?

Das Problem ist, dass man globale Objekte vermeiden sollte wann immer es möglich ist.
Ja - weshalb denn? Nenne bitte einen nachvollziehbaren Grund.

Manchmal lässt es sich nicht vermeiden ein Objekt global anzulegen, aber jedes globale Objekt erzeugt auch Probleme wie schlechte Testbarkeit.
Auch das ist nur eine pauschale Aussage. Es wäre schön, wenn Du Deine Behauptungen auch untermauern würdest...
Thomas Nitzschke
Google Maps mit Delphi
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

AW: Referenz Verwaltung

  Alt 21. Jun 2012, 18:53
Weshalb soll man "Smart Pointer", "Smart Interfaces" oder wie immer solche Dinge auch genannt werden, nicht verwenden? Weil sie nicht "etabliert" sind?
Nein, weil der Programmierer damit seine schlechte Struktur (globale Objekte, keine Vorstellung über die Lebendauer von Objekten) überdeckt was langfristig zu schlecht wartbarem Code führt.

... dass man globale Objekte vermeiden sollte wann immer es möglich ist.
Ja - weshalb denn? Nenne bitte einen nachvollziehbaren Grund.
Also das gehört zu den Grundlagen eines jeden Programmierers, der sein Handwerk ernsthaft betreibt.
http://c2.com/cgi/wiki?GlobalVariablesAreBad
Andreas
  Mit Zitat antworten Zitat
Antwort Antwort


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 23:16 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