delphi - Why is an interface in the sub class not released -


i'm facing following situation , i'm wondering code leaking memory. let have following interfaces , implementations:

type itools = interface   function helloworld : string; end;  idatabase = interface   function query(aquery : string) : string; end;  imanager = interface   procedure execute; end;  tdatabase = class(tinterfacedobject, idatabase)   strict private     ftools : itools;   public     constructor create;     destructor destroy; override;     function query(aquery : string) : string; end;  ttools = class(tinterfacedobject, itools)   strict private     fdatabase : idatabase;   public     constructor create(adatabase : idatabase);     destructor destroy; override;     function helloworld : string; end;  tmanager = class(tinterfacedobject, imanager)   strict private     fdatabase : idatabase;   public     constructor create;     procedure execute; end;  

now, if create example this:

procedure example; var    lexample : imanager; begin   lexample := tmanager.create;   lexample.execute;   lexampe := nil; // should not necessary end; 

where fdatabase tmanager created tdatabase , passed in constructor of ttools, has same (?) object / interface in ttools in tmanager. lexample leaks memory, because of interfaces / objects in sub class (idatabase). why isn't interface released? or don't understand of delphi fundamentals?

why isn't interface released?

you have circular reference.
tdatabase contains reference ttools , ttools contains reference tdatabase.
because delphi not have garbage collector not able resolve these circular references without help.

if using mobile nexgen compiler, or d10.1 berlin solution declare tdatabase as:

tdatabase = class(tinterfacedobject, idatabase)   strict private     [weak]          <<--     ftools : itools;   public     constructor create;     destructor destroy; override;     function query(aquery : string) : string; end; 

the [weak] attribute trigger delphi generate different code when ftools assigned. , runtime keep bookkeeping if reference count of interface goes 0 object not destroyed if weak reference happens not involved in circular reference.
marco cantù writes here: http://blog.marcocantu.com/blog/2016-april-weak-unsafe-interface-references.html
writes [unsafe] attribute. don't use one, unless know means, it's not need.

you should mark 1 of circular references [weak]! if mark both mishaps occur.

what if compiler not support [weak]?
if using older delphi windows or osx targets solution follows.

use hack described by: http://blog.dummzeuch.de/2014/06/19/weak-references-or-why-you-should-enable-reportmemoryleaksonshutdown/

    procedure setweak(_interfacefield: piinterface; const _value: iinterface);     begin       ppointer(_interfacefield)^ := pointer(_value);     end;      type       tchild = class(tinterfacedobject, ichild)       private         fparent: iparent; // must weak reference!       public         constructor create(parent: iparent);         destructor destroy; override;       end;      constructor tchild.create(parent: iparent);     begin       inherited create;       setweak(@fparent, parent);     end;      destructor tchild.destroy;     begin       setweak(@fparent, nil);       inherited;     end; 

what make reference in underhanded way reference count not go permanently.
not hack not have full protection against mishaps [weak] attribute gives.
if weak reference happens not involved in circular reference might have premature destruction of fparent.

arnaud bouchez has more detailed write-up in blog; recommend read it: http://blog.synopse.info/post/2012/06/18/circular-reference-and-zeroing-weak-pointers


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -