Einzelnen Beitrag anzeigen

Dax
(Gast)

n/a Beiträge
 
#7

Re: Implementierung eines Interfaces

  Alt 18. Jun 2006, 16:17
Kann ich:

Referenzzählung bei Interfaces ist ähnlich wie die von Strings. Pro Interface-Variable, der eine Instanz der implementierenden Klasse zugewiesen wird, wird der Referenzzähler dieser Klasseninstanz um 1 erhöht. Rennt die Variable aus dem Scope, wird der Zähler entsprechend um 1 verringert. Sobald der Zähler auf 0 fällt, gibt sich die Klasse automatisch frei - kein Speicherleck entsteht, wenn der ursprüngliche Zeiger auf die Klasseninstanz verloren ist. So weit, so gut.

Aber was passiert hier?
Delphi-Quellcode:
IMyInterface = interface
    function GetPartner: IMyInterface;
  end;

TMyClass = class(TInterfacedObject, IMyInterface)
private
  fPartner: IMyInterface;
  procedure SetPartner(const Value: IMyInterface);
  function GetPartner: IMyInterface;
public
  property Partner: IMyInterface read GetPartner write SetPartner;

...

var
  His, Her: TMyClass;

His := TMyClass.Create();
Her := TMyClass.Create;

His.Partner := Her;
Her.Partner := His;
Die Zuweisung ist korrekt. Beide implementieren IMyInterface, also wirds hier nicht knallen.

Jetzt stell dir vor, His rennt aus dem Scope. His' Referenzzähler dropt auf 1. Bei Her ist es genauso. Wenn beide aus dem Scope rennen, droppen beide Zähler auf 1! Speicherleck! Die Klassen hinter den Interfaces werden nicht mehr freigegeben.

Nimm mal dieses C#-Programm und lass es laufen:
Code:
namespace GCTest
{
   interface IPerson {
      IPerson Partner {get; set;}
   }
   
   class Person : IPerson
   {
      int[] DNA = new int[512];
      
      private IPerson partner;
      public IPerson Partner {
         get { return partner; }
         set { partner = value; }
      };
   }
   
   class MainClass
   {
      public static void Main(string[] args)
      {
         while(true) {
            IPerson he, her;
            he = new Person();
            her = new Person();
            he.Partner = her;
            her.Partner = he;
         }
      }
   }
}
Währenddessen beobachte die Speicherauslastung. Es werden jede Menge Paare erstellt - aber die Speicherauslastung geht (bei mir zumindest) nie über 5MB hinaus. Das ist GarbageCollection. Der GC erkennt automatisch, das keine nutzbare Referenz auf die Instanzen mehr vorhanden ist und killt diese aus dem Speicher. Es gibt zwar noch Referenzen - die partner-Referenzen - aber mit denen kann das Programm nix mehr anfangen.

Probiere das selbe in Delphi, und bald wird dein Rechner mit der swapperei anfangen^^

Conclusio: Wenn schon GC, dann richtig
  Mit Zitat antworten Zitat