[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