[fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)

Tony Whyman tony.whyman at mccallumwhyman.com
Wed Oct 5 18:13:50 CEST 2016


On 05/10/16 16:26, Marcos Douglas wrote:
> Tony Whyman had posted on August 10 a problem with the compiler using 
> Delegates.
> He used a workaround to "solve" his problem and the thread died.

Marcos,

I believe I concluded that this could be a bug or feature. Either way it 
is a Bear Trap waiting for the unwary programmer and it would be nice if 
in some way the implementation could be improved. The problem, as I see 
it is:

Basics:

1. Whenever an interface reference is coerced from an interfaced object, 
the object's reference count is incremented.

2. When the interface is copied that reference count is again incremented.

3. When the interface goes out of scope, the reference count is 
decremented and when it reaches zero, the object is freed.

So far so good, but, when you have a delegated interface:

Terminalogy: In the example:

     TMyValue = class(TInterfacedObject,IValue);

     TMyObject = class (TinterfacedObject,IMyInterface)
     ...
     property Value: IValue read FValue implements IValue;
     end;

     Then a TMyValue object "is the source of" the delegated interface.
     A TMyObject object "provides" the delegated interface.

4. Whenever an interface reference to a delegated interfaced is coerced 
from an interfaced object, it is the reference count of the object that 
"is the source of" the delegated interface that is incremented.

5. When the interface is copied the reference count of the object that 
"is the source of" the delegated interface is incremented.

6. When the interface goes out of scope, the reference count of the 
object that "is the source of" the delegated interface is decremented 
and when it reaches zero, that object is freed.

7. You are responsible for freeing the object that "provides" the 
delegated interface.

To me this is counter-intuitive behaviour and this counter-intuitiveness 
is compounded by the case where:

a. An interfaced object provides only a delegated interface.

b. An inherited interface (e.g. IUnknown) is coerced from the object.

In this case, the reference count incremented is that of the object that 
"provides" the delegated interface  and not the object that "is the 
source of" the delegated interface.

Where do we go from here?
======================

Provided you understand what is happening then it works - but there is 
no real documentation and it is really easy to get this wrong.

For me the consistent approach should be that when you coerce an 
interface from an object, the reference count of the object that 
"provides" the delegated interface is always the one that is incremented 
and the interface remains tied to that object  An object that "is the 
source of" a delegated interface should always have its lifetime tied to 
that of the object that "provides" the delegated interface. i.e. it has 
an implicit reference to the object that is the source of the interface.

Tony Whyman
MWA




More information about the fpc-pascal mailing list