Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Referenz Verwaltung (https://www.delphipraxis.net/168985-referenz-verwaltung.html)

Jonas Shinaniganz 21. Jun 2012 15:48

Referenz Verwaltung
 
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.

jaenicke 21. Jun 2012 16:20

AW: Referenz Verwaltung
 
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. :wink: Was du davon hältst findest du am besten selbst heraus. :wink:

shmia 21. Jun 2012 16:38

AW: Referenz Verwaltung
 
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.

Thom 21. Jun 2012 16:55

AW: Referenz Verwaltung
 
Zitat:

Zitat von shmia (Beitrag 1171953)
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...

Zitat:

Zitat von shmia (Beitrag 1171953)
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?

shmia 21. Jun 2012 17:16

AW: Referenz Verwaltung
 
Zitat:

Zitat von Thom (Beitrag 1171957)
Zitat:

Zitat von shmia (Beitrag 1171953)
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.
Zitat:

Zitat von Thom (Beitrag 1171957)
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.

Thom 21. Jun 2012 17:30

AW: Referenz Verwaltung
 
Zitat:

Zitat von shmia (Beitrag 1171962)
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?

Zitat:

Zitat von shmia (Beitrag 1171962)
Das Problem ist, dass man globale Objekte vermeiden sollte wann immer es möglich ist.

Ja - weshalb denn? Nenne bitte einen nachvollziehbaren Grund.

Zitat:

Zitat von shmia (Beitrag 1171962)
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...

shmia 21. Jun 2012 18:53

AW: Referenz Verwaltung
 
Zitat:

Zitat von Thom (Beitrag 1171965)
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.

Zitat:

Zitat von Thom (Beitrag 1171965)
Zitat:

Zitat von shmia (Beitrag 1171962)
... 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

Namenloser 21. Jun 2012 19:36

AW: Referenz Verwaltung
 
Eigentlich hat das nichts mit globalen Variablen zu tun.

Es kann einfach sein, dass man das selbe Objekt an zwei verschiedenen Stellen verwendet, wobei es von der einen Stelle freigegeben wird. Die andere Stelle kriegt davon aber nichts mit und hat keine Möglichkeit zu überprüfen, ob das Objekt noch existiert, weil Assigned nur den Pointer auf nil prüft.

Für den Fall, dass man ein Objekt nur an einer einzigen Stelle verwendet, gibt es FreeAndNil, aber bei mehreren, unabhängige Referenzen hilft das nichts. Mal unabhängig davon, dass man immer leicht alles pauschal als „schlechtes Design“ abtun kann, ist das irgendwie asymmetrisch.

Man kann das Problem natürlich „klassisch“ mithilfe eines Observer-Patterns o.ä. angehen (so ähnlich wie es die VCL afaik auch macht), aber das ist erstens umständlich und zweitens wieder eine potenzielle Fehlerquelle, weil man jedes mal darauf achten muss, manuell einen Observer hinzuzufügen oder zu entfernen.

Ein Smart-Pointer automatisiert das Prozedere einfach nur und wäre daher aus meiner Sicht eine Verbesserung – schlechtes Design gibt es mit und ohne Smart Pointer. Aber mit Smart-Pointer hat man zumindest eine Fußangel weniger, an der es knallen kann.

Und an dieser Stelle muss ich natürlich noch mal auf meine Frickel-Lösung aus diesem Thread verweisen, der das gleiche Thema hatte ;). Vielleicht fühlt sich ja jemand inspiriert und entwickelt etwas daraus, das man tatsächlich einsetzen kann (eventuell mithilfe von neuen Sprachfeatures wie Generics, die ich unter TDE leider nicht zur Verfügung habe)...

shmia 21. Jun 2012 22:35

AW: Referenz Verwaltung
 
Zitat:

Zitat von NamenLozer (Beitrag 1171978)
Eigentlich hat das nichts mit globalen Variablen zu tun.
Es kann einfach sein, dass man das selbe Objekt an zwei verschiedenen Stellen verwendet, wobei es von der einen Stelle freigegeben wird.

Genau hier liegt der Hase im Pfeffer!
Der Entwickler muss eben genau die Lebenzeiten seiner Objekte unter Kontrolle halten.
Wenn man sich die Lebenszeit eines Objekts als Rechteck vorstellt, dann besteht die Kunst darin, die Rechtecke so ineinander zu schachteln, dass sich die Grenzen nicht überschneiden.
Wenn es ein Objekt A gibt, dass von Objekt B und C benützt wird, dann wird einfach ein Objekt D benötigt, dass alle 3 Objekte in der richtigen Reihenfolge erzeugt und zerstört.
Und Probleme entstehen auch dadurch, dass häufig nicht erkannt wird, dass dieses Objekt D benötigt wird.
Und wenn Objekt A von B und C benötigt wird, dann wird A eben vor B und C erzeugt und nach B und C zerstört.

Globale Objekte stören diese Ordnung, da sie potentiell länger leben können als das Hauptformular.

Bummi 21. Jun 2012 23:10

AW: Referenz Verwaltung
 
ich hatte bereits vor einiger Zeit in einem Thread von stahli (der sich seit längerem intensiv mit diesem Thema auseinanderzusetzen scheint) vorgeschlagen eine weitere Dereferenzierung vorzunehmen. Die "Zeiger" also global zu halten und nur noch Zeiger auf die "Zeiger" zu übergeben. Bei dieser Vorgehensweise müsste IMHO bei korrekter Implementierung alles wie gewünscht funktionieren.

Namenloser 21. Jun 2012 23:28

AW: Referenz Verwaltung
 
@shmia: Nicht jede Anwendung ist eine Formularanwendung.

Ich stelle mir jetzt mal beispielhaft ein Spiel vor: Es geht um Raketen und Raketenabwehrsysteme, jede Rakete ist ein Objekt. Wenn ein Raketenabwehrsystem eine feindliche Rakete detektiert, schickt es eine Abwehrrakete los, die die Rakete verfolgt. Dazu wird der Abwehrrakete bei Erstellung eine Referenz auf die feindliche Rakete gegeben.

Die Abwehrrakete liest nun bei jedem Bewegungsschritt die Position der feindlichen Rakete aus und passt entsprechend ihre Flugrichtung an. Wenn die Abwehrrakete mit der feindichen Rakete kollidiert, explodieren beide und die Objekte werden freigegeben.

Soweit so gut – aber was, wenn es ein zweites Raketenabwehrsystem gibt, das ebenfalls eine Abwehrrakete auf das gleiche Ziel losgeschickt hat? Dann befindet sich die Rakete des 2. Abwehrsystems noch in der Luft, während die feindliche Rakete explodiert – und verfolgt forthin ein Objekt, das gar nich mehr existiert.

Sir Rufo 22. Jun 2012 00:47

AW: Referenz Verwaltung
 
Zitat:

Zitat von NamenLozer (Beitrag 1171995)
Soweit so gut – aber was, wenn es ein zweites Raketenabwehrsystem gibt, das ebenfalls eine Abwehrrakete auf das gleiche Ziel losgeschickt hat? Dann befindet sich die Rakete des 2. Abwehrsystems noch in der Luft, während die feindliche Rakete explodiert – und verfolgt forthin ein Objekt, das gar nich mehr existiert.

Das ist dann falsch implementiert ;)
Denn es ändert sich bei der "Zerstörung im Spiel" erst mal nur der Zustand in "zerstört". Deshalb muss aber das Objekt selber nicht gleich zerstört werden.

Hier würde sich auch die Verwendung von Interfaces anbieten.

BUG 22. Jun 2012 01:22

AW: Referenz Verwaltung
 
Zitat:

Zitat von Sir Rufo (Beitrag 1171998)
Hier würde sich auch die Verwendung von Interfaces anbieten.

Ich glaube, es ging eher darum, klar zu machen, dass eine hierarchische Organisation von Objekte, wie sie shmia fordert, nicht immer sinnvoll/möglich ist.

Zitat:

Zitat von shmia (Beitrag 1171992)
Wenn man sich die Lebenszeit eines Objekts als Rechteck vorstellt, dann besteht die Kunst darin, die Rechtecke so ineinander zu schachteln, dass sich die Grenzen nicht überschneiden.

Um mir die Lebenszeit eines Objekts als Rechteck und nicht auf einem Zeitstrahl vorzustellen, fehlt mir allerdings die Phantasie :gruebel:

Namenloser 22. Jun 2012 01:39

AW: Referenz Verwaltung
 
Zitat:

Zitat von Sir Rufo (Beitrag 1171998)
Zitat:

Zitat von NamenLozer (Beitrag 1171995)
Soweit so gut – aber was, wenn es ein zweites Raketenabwehrsystem gibt, das ebenfalls eine Abwehrrakete auf das gleiche Ziel losgeschickt hat? Dann befindet sich die Rakete des 2. Abwehrsystems noch in der Luft, während die feindliche Rakete explodiert – und verfolgt forthin ein Objekt, das gar nich mehr existiert.

Das ist dann falsch implementiert ;)
Denn es ändert sich bei der "Zerstörung im Spiel" erst mal nur der Zustand in "zerstört". Deshalb muss aber das Objekt selber nicht gleich zerstört werden.

Ja, in der Regel implementiert man das in der Praxis auch so. Aber das Problem bleibt letztlich trotzdem, denn irgendwann muss man das Objekt endgültig entfernen, wenn man kein Memory Leak haben will. Das Beispiel sollte aber sowieso nur zur Veranschaulichung dienen.

Man kann immer alles auch anders lösen, keine Frage – aber man kann auch auf Klassen als Sprachkonstrukt verzichten und stattdessen wieder mit Records und Funktionen programmieren. Klassen erleichtern aber die Arbeit; Smart-Pointers ebenso.

Jonas Shinaniganz 22. Jun 2012 08:18

AW: Referenz Verwaltung
 
Okay nachdem Ich alles sorgfältig gelesen habe entscheide Ich mich definitiv für "Smart Pointer".

Pros:
- Ich werde keine Referenzen mehr haben die auf freien Speicher zeigen und kann vor Zugriffen auf NIL prüfen
- Meine Objekte sind sehr "verworren :?: " und die Lebenszeit ist schwer abzuschätzen, Smartpointer bieten sich an
- Designfehler wurden in der Vergangenheit gemacht und es ist nicht möglich diese jetzt anzugehen

Cons:
- Das erkaufe Ich mir durch ermöglichen/fördern von schlechtem Design
- Die Implementation ist scheinbar halbherzig weil es kein vollständiger Garbagecollector ist :?:
- Beim mischen von Interfaces und Objecten muss man vorsichtig sein

Das Ich Globale Variablen vermeiden soll und werde habe Ich schon vor längerer Zeit für mich entschieden.

Also insgesammt kann ein Smartpointer scheinbar nicht schaden, er HINDERT einen ja nicht an gutem Design und löst mein Problem.
Deswegen entscheide Ich mich für Smartpointer und lese jetzt eure Verweise um eine möglichst schnittige Implementierung hinzubekommen,

beste Grüße!

Furtbichler 22. Jun 2012 08:49

AW: Referenz Verwaltung
 
Wenn ich mein Programmdesign so aufbaue, das es für alle Instanzen jeweils eine Entität gibt, die dafür zuständig ist (ein anderes Objekt oder eine Klasse bzw. die Unit für unsere globalen Freunde), dann stellt sich das Problem nicht, das ich auf Instanzen zugreife, die nicht mehr existieren. Eine Ausnahme stellen zirkuläre Bezüge dar, die dann aber aufgelöst werden können, sodaß die Grundregel (Zuständigkeiten!) wieder greift.

Ich möchte die Kontrolle haben, wann genau ein Objekt freigegeben wird.

Es kann sein, das ich dann im Design etwas statischer agieren muss, und nicht mehr so elegant arbeiten kann. Aber sicherer bin ich damit in jedem Fall. Wenn man das stringent durchzieht, hat so ein Design auch eine gewisse Ordnung bzw. Eleganz. Ja gut, altbacken. Aber solide. Die Abhängigkeiten sind nur in einer Richtung.

Bei Interfaces habe ich diese natürlich Probleme nicht. Sie sind ein mächtiges Werkzeug, aber ich muss damit umgehen können.

Arbeite ich mit Interfaces dann weiss ich nicht, wann die Objekte freigegeben werden, was ganz praktisch ist. Aber beim Design muss ich aufpassen, das ich nicht Objekte wie Kraut und Rüben (Zirkuläre Bezüge) instantiiere und Abhängigkeiten erzeuge, die ich nicht mehr verstehe.

Jonas Shinaniganz 22. Jun 2012 10:22

AW: Referenz Verwaltung
 
... kann gelöscht werdem

Jonas Shinaniganz 22. Jun 2012 14:51

AW: Referenz Verwaltung
 
Ich bin auch noch über ein altes Thema gestolpert:

http://www.delphipraxis.net/100110-v...ls-zeiger.html

Der arme neomic hat sich zum Schluss eine Steuerung gebastelt die Ich in einem Projekt ab 3 Units nicht mehr verwenden möchte :D
Da konnte ich mich doch glatt selbst wiedererkennen!

Aber ein Sehr wertvoller Beitrag von Dezipaitor. (Für mich "Sehr wertvoll")


Zitat:

Also der Zeiger an sich ist einfach eine Zahl. Die Zahl gibt ja an, wo im Speicher sich die Information zum Auto befindet. Wenn du nun diesen Zeiger kopierst, dann wird nur der Wert kopiert und du hast zwei gleiche Werte,die auf denselben Speicher zeigen. Wenn du nun einen Wert auf 0 (also nil) setzt, dann bleibt der andere Zeiger unbeheligt davon.
Wenn du nun mehrere Zeiger auf das Auto hast und du verwendest einen Zeiger, um den Speicher des Autos zu löschen, dann hast du plötzlich mehrere Zeiger, die an die alte Stelle der Autoinformation zeigen. Jetzt ist der Speicher jedoch ungültig. Das führt zu Problemen (Merkwürdiges, AV).
Es gibt eine Technik mit dem Namen Referenzzählung (Reference counting), die macht folgendes, um das Problem zu verhindern:
Das Objekt (Auto) bekommt eine Integer Variable, die angibt, wieviele Zeiger auf das Objekt zeigen. Wenn diese Variable 0 ist, dann kann das Objekt gefahrlos gelöscht werden. Wenn es größer als 0 ist, dann darf es nicht gelöscht werden.
Bei jedem Erzeugen eines Zeigers auf das Objekt, wird diese Variable um eines erhöht. Bei jedem Löschen (nil-setzen!!) eines Zeigers auf das Objekt, wird diese Variable um eins erniedrigt. Für Singlethread Programme wars das auch schon.

Eine zweite Technik (deren Namen ich vergessen habe), funktioniert so:
Es gibt nur eine Zeigervariable (Hauptzeiger), die direkt auf das Objekt zeigt. Alle neuen Zeiger zeigen auf diese Zeigervariable. Folgedessen muss diese Zeigervariable im Heap existieren (erzeugt durch GetMem oder New). Wenn man auf das Objekt zugreifen will,
dass muss man zweimal referenzieren. Zuerst den Zeiger auf den Hauptzeiger und dann darüber auf das Objekt. Alle Zeiger zeigen eben zuerst auf den Hauptzeiger. Wenn man nun das Objekt löscht, dann setzt man den Hauptzeiger auf nil (nicht FreeMem der Dispose machen!) und alle andere Zeiger zeigen dann auf nil.
Natürlich muss man diese Hauptzeiger auch irgendwann mal löschen. Mann kann sie mit der Referenzählung verwalten oder in einer List verwalten, die dann ganz zum Schluss gelöscht wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:07 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