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

stdreamer stdreamer at freemail.gr
Fri Oct 7 19:20:22 CEST 2016

On 07/10/2016 18:33 μμ, Marcos Douglas wrote:
> The problem is: The user (programmer) needs to know (previously) if
> such classes can or not be used as a contained object!

True then again that is true for all objects not only interfaces. You 
need to understand what they address how they address it and what are 
their short comings to use them to their full extend.

> We don't need "clean up properly" instances that is interface-based.
> If this solve the problem for contained objects, I'll do it!
> BUT, if I do this I can forget all about  TContainedObject or
> TAggregatedObject? If I can't, this not make sense.

Well this makes me think that you do not understand the difference 
between heap based and stack based variables. You do understand that a 
variable on the heap never goes out of scope, which makes automatically 
decreasing the reference counter impossible, right? You have to nil it 
manually and this is true in C++ as well.

> "...to a language feature that has nothing to do with it."
> Your opinion.

I wish.

> I've been using COM Interfaces (ref-counting) for years without
> problems of memory leaks.
> I just want to use the feature "delegation". That's it. But the design
> of this solution looks wrong. Not only in FPC, but Delphi too — as
> said Graeme.
> The documentation recommends nothing about TContainedObject or
> TAggregatedObject on topic about Delegates.

of course not, contained objects is one solution it can be reversed as 
well ee the contained object is in fact the object that used the 
delegate and depending on the design it can be passed as parameter in 
the constructor or changed through the property to something else that 
is not contained at all. It so happens that you are using the contained 
object logic.

To be clear I have no objection in mentioning the pitfalls in the 
documentation and show the tcontainedobject as a possible solution to 
the problem.

> IMHO this is a problem. You guess not, but you just know a workaround.
> There is a design problem. Maybe there is no solution. Maybe is so
> hard to fix that don't worth. I don't know... but there is a problem.
> It's a fact.

I disagree the use of "fact" in this context is wrong but hey what ever 
floats your boat.

>>> If somebody says: "You should know these classes..." or "you should
>>> know what you're doing..."
>>> I will answer: this is not about OOP, just procedural. OOP is about
>>> encapsulation. If I need to see the class' code, this means that it
>>> was not well done.
>> No! Any object solves a single problem. If it does not fit in your own
>> design then you either have the wrong design or you need to customize the
>> object to include your use case. In both cases you need to read up and
>> understand which use cases is solving, how it does it and how you can extend
>> it to support your own use cases. It is not responsible to accommodate your
>> assumptions.
> So, if I understood right, you saying that:
> If I have a function that expects an IStream interface as argument, I
> can't pass any class that implements that interface BEFORE see which
> hierarchy it belongs? If I will can use as "contained", "aggregated"
> or just "stand alone"?

That is a use case and no I never said that your use cases are wrong 
invalid or improper.

>> Can things get better? Sure every change no matter of its size, moves the
>> library forward but if that change is appropriate for the library can only
>> be decided by the library maintainers and you (or me for that matter) crying
>> wolf does not help.
> So, I can change the hierarchy of my classes and break the whole project?
> Is it correct and makes sense for you?
> I truly know that is not about encapsulation or about object-oriented
> programming.

I have to question a design that changing a single inheritance breaks 
the library. If this is such a big problem then don't change your 
hierarchy make sure that you are properly setting all interfaces in the 
heap to nil when you are finished using them and forget about everything 

Or go the opposite route create an IContained interface that 
encapsulates the code in TContainedObject  and tell your team that you 
can use any class that implements IContained as a delegate.

There are a lot of designs to pick from and every one has its pros and 
cons pick one that fits in your design.

>> For me extending the TContainedObject to support both contained and stand
>> alone use is trivial I bet you can do it as well now that you know where to
>> look.
> That is a good idea.
> If is possible. If doesn't have any "compiler magic" inside this
> classes, I will do it.
> Better. I will copy the implementation of these classes to create my
> own implementations.

That's the spirit use the library to your advantage and if you have the 
time, inclination and will, post a proposition for a new class giving 
the use cases it addresses.

>> I'm against adding that kind of functionality to TContainedObject as
>> it is outside of its designed goal.
> I agree...
>> If a new object adds more value or more bloat to the library is up to the
>> maintainers to decide.
> ...but IMHO, it would be a better design if these classes do not exist
> for this purpose.

Well I learned from them, used them verbatim and customized them to my 
use cases, they are an asset in the library a reference point and they 
are a good reference too, so I have to disagree I guess.

More information about the fpc-pascal mailing list