Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Friday 11 November 2016 07:48:54 Lars wrote: > On Thu, November 10, 2016 11:04 pm, Martin Schreiber wrote: > > On Friday 11 November 2016 04:21:31 Lars wrote: > >> Replying to an old thread in my inbox. Apologies if it's obsolete as it > >> is a month old. > > > > I don't think such themes are allowed in fpc-pascal. > > If an oberon like garbage collector, instead of reference counting, could > be somehow implemented into fpc, then it's still on topic. > > However, oberon garbage collector is likely to alien to apply to fpc. > I just wonder, since fpc is based on Wirth's work, if any fpc developers > have looked into how oberon does garbage collection, and applied this > knowledge to fpc. I tried to keep it as much on topic, in that sense - but > I understand it's not 100 percent fpc (as it currently stands) related. True, but my possible answers probably are below the tolerated level. ;-) Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thu, November 10, 2016 11:04 pm, Martin Schreiber wrote: > On Friday 11 November 2016 04:21:31 Lars wrote: > >> >> Replying to an old thread in my inbox. Apologies if it's obsolete as it >> is a month old. >> > I don't think such themes are allowed in fpc-pascal. If an oberon like garbage collector, instead of reference counting, could be somehow implemented into fpc, then it's still on topic. However, oberon garbage collector is likely to alien to apply to fpc. I just wonder, since fpc is based on Wirth's work, if any fpc developers have looked into how oberon does garbage collection, and applied this knowledge to fpc. I tried to keep it as much on topic, in that sense - but I understand it's not 100 percent fpc (as it currently stands) related. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Friday 11 November 2016 04:21:31 Lars wrote: > > Replying to an old thread in my inbox. Apologies if it's obsolete as it is > a month old. > I don't think such themes are allowed in fpc-pascal. Please continue the discussion on MSEide+MSEgui mailinglist: https://lists.sourceforge.net/lists/listinfo/mseide-msegui-talk Archive: https://www.mail-archive.com/mseide-msegui-talk@lists.sourceforge.net/ Thanks, Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Wed, October 5, 2016 9:54 pm, Martin Schreiber wrote: > On Thursday 06 October 2016 00:16:22 Tony Whyman wrote: > >> On 05/10/16 23:03, Graeme Geldenhuys wrote: >> >>> Martin Schreiber recently mentioned in another Interface discussion >>> that there is a very good reason he doesnât use COM style >>> interfaces⦠Reference Counting! >>> >> >> Used properly reference counted interfaces are very powerful and allow >> for some very elegant programming. Do you complain about AnsiStrings? >> They are reference counted. Would you really want to have to free every >> string explicitly? Dynamic arrays are similarly reference counted. >> > Reference counting is great for simple types like strings and dynamic > arrays but is a nightmare with the venturesome mixture of COM-interface > and classes from Delphi. Even reference counting for complex classes is no > good idea IMO, I fear the times when FPC will implement ARC. > I don't think that a programming language should hide more and more of the > internal working of the code he writes from the programmer. Take a look > at the modern C++ programs; the LLVM-compiler is a good example. It is > horrific slow. Stepping through the code shows that there are complex > multi-level dynamic type conversion and dataaccess routines at almost > every statement. The typical C++ programmer does not need to care about > because the programming language takes care for the boring tasks. The > typical C++ programmer actually *does* not care about performance because > competing programs are not faster; they are written in a modern > programming language too... Recently I had to revive my stone old AMD-K6 PC > with Windows 95. What marvel, that relict with its age-old applications > provides a better user experience, is snappier, more convenient and more > productive than my newest Linux machine with the modern desktops and > applications. > > Martin Replying to an old thread in my inbox. Apologies if it's obsolete as it is a month old. Martin, as you know, Windows 95 is mostly coded in plain C, so guess what that meant: you had to reboot your pc every day to reset all the memory leaks. So your idea that we should not be hiding code with more abstraction layers is a double edged sword. Windows 95 is a very zippy, fast, snappy operating system. But it also was not garbage collected so had memory leaks due to poor programming in plain C. Remember when people migrated over to Windows 2000 and Windows XP and found that they no longer needed to restart their PC daily to reset the memory leaks? Sometimes my windows 98 computer would last for a week, and that was about it before I had to restart. Usually I had to restart every 1-3 days. And why is that? Because windows 95/98 did not have an abstract programming language in place which hid details. It's all manual memory management which causes tons of bugs. And these bugs are the same issue seen in all kinds of delphi/lazarus apps Admitting, however, that Windows 2000 and XP did not migrate to any garbage collected language, they just improved the old buggy code so that there were less memory leaks and now instead of rebooting your PC every day or 3 days, you can wait a month before rebooting, or sometimes a couple weeks, or sometimes a week. But there are still bugs in win2000/windows10/windows7 which cause me having to reboot my PC. And wow, Firefox needs to be constantly restarted, as the memory leaks grow out of control. But that's not a plain C app. At the same time, I'm also scared of reference counting as you are, for classes, as garbage collection mechanism. But since you are against hiding details from the programmer, what's your opinion of Oberon garbage collection that Wirth designed, if it was somehow implemented in FPC? Likely that won't happen. However you say you are against hiding too many details from the programmer (abstraction) so you think Oberon's garbage collection system is too high level and would prefer to free and create? To keep it on topic, related to fpc, and to not divert to oberon discussion only: are you saying that if somehow and oberon like garbage collection was implmented in fpc you'd be against that as it is too abstract, or are you saying you are just against reference counting, but would accept an Oberon like garbage collection? Unfortunately, that means more like a new programming language rather that continuing fpc as it is, likely. As oberon is designed to be that way, to handle garbage collection and even module unloading/loading at run time, whereas fpc not so much. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/2016 18:33 μμ, Marcos Douglas wrote: 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. OK this needs a bit more information. The interface variable is only a half measure. It assumes and expects that the container (the object that has a delegation) will always get destroyed after all references to the delegated interface are released. It does not check for it and it leaves everything to the programmer. If the contained interface needs the container to function properly then a number of of exception will be raised as soon as the container gets freed. The TContainedObject on the other hand makes sure that the container can not be destroy as long as there are references on the contained interface which is a much safer solution. I have used both with success in the past I still prefer the TContainedObject approach for this little extra piece of mind that it provides me. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
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 else. 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
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 12:33 PM, Marcos Douglas wrote: >> 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. I seen now (D7source). It looks pretty simple. The TAggregatedObject has this attribute: FController: Pointer; // weak reference to controller :) This is a workaround. I need to do another one. That's Okay because everything is going to be encapsulated in TAggregatedObject (or in another new class) and for the users (programmers) that will be transparent. @stdreamer Anyway, thank you for the advice about this class. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 11:46 AM, stdreamer wrote: > On 07/10/2016 16:12 μμ, Marcos Douglas wrote: >> >> The team shouldn't know about the hierarchy; about how was implemented >> these classes. >> They can use TDataStream directly or as a contained object. >> But as I understood, we need to use TContainedObject or >> TAggregatedObject only in these "special cases" > > You are correct the TContainedObject can only be used with a root object, > now what? Is this a block for you? Of course! As I explained before. > It is not the library's responsibility to solve your problems only to > assist. TContainedObject is a basic solution which is generic enough to > accommodate 90% (assumed number just to emphasize its usefulness) of the use > cases. > Now why is your use case special enough to be included in the library it > self? The problem is: The user (programmer) needs to know (previously) if such classes can or not be used as a contained object! >> I didn't test yet. I will. But if I'm right, ie, if TDataStream is >> inherited from TContainedObject and, because that, I can not use >> TDataStream as a simple instance, without a "root" object... well, >> this design is wrong. > > > well let me see > You failed to clean up properly after your code (a simple fValue := nil in > TMyApp.Destroy method should solve all your problems), 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. >... you did not knew the > basic mechanisms provided for the exact problem you are having and you > attached your design sort comings to a language feature that has nothing to > do with it. All in all, you have failed to do your homework. I should listen > to your opinion about design . why exactly? "...to a language feature that has nothing to do with it." Your opinion. 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. 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. >> 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"? > 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. > 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. > 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. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 11:02 AM, Tony Whyman wrote: > ...As a workaround for the interface delegation problem it works, as long as > you don't try and use TDelegateClass on its own As I said... sad. Regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/2016 16:12 μμ, Marcos Douglas wrote: The team shouldn't know about the hierarchy; about how was implemented these classes. They can use TDataStream directly or as a contained object. But as I understood, we need to use TContainedObject or TAggregatedObject only in these "special cases" You are correct the TContainedObject can only be used with a root object, now what? Is this a block for you? It is not the library's responsibility to solve your problems only to assist. TContainedObject is a basic solution which is generic enough to accommodate 90% (assumed number just to emphasize its usefulness) of the use cases. Now why is your use case special enough to be included in the library it self? I didn't test yet. I will. But if I'm right, ie, if TDataStream is inherited from TContainedObject and, because that, I can not use TDataStream as a simple instance, without a "root" object... well, this design is wrong. well let me see You failed to clean up properly after your code (a simple fValue := nil in TMyApp.Destroy method should solve all your problems), you did not knew the basic mechanisms provided for the exact problem you are having and you attached your design sort comings to a language feature that has nothing to do with it. All in all, you have failed to do your homework. I should listen to your opinion about design . why exactly? 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. 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. 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. I'm against adding that kind of functionality to TContainedObject as it is outside of its designed goal. If a new object adds more value or more bloat to the library is up to the maintainers to decide. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/16 12:29, stdreamer wrote: No! Delegation is a mechanism, when used, you have to know exactly how it works. Delegation is only used to minimize code instead of writing a bunch of procedures that call the contained object's methods. That's it and nothing more. I believe that I now understand the issues around interface delegation and how to use it. You are correct, it's only an optimisation - and it sucks. I would never recommend anyone to use interface delegation as you have to only put a "foot wrong" and can end up memory leaks on one side, or access violations on the other. Writing a "bunch of procedures" may be tedious but it's less work in the end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/16 12:29, stdreamer wrote: The point is that you are trying to equate delegation with contained objects/interfaces and that is not what delegates are about. Delegation has nothing to do with the underlined mechanism you choose to use. Hmm, not so sure about that. I have updated my original example from August to use TContainedObject (see below). As a workaround for the interface delegation problem it works, as long as you don't try and use TDelegateClass on its own. This is because although it appears as a reference counted com interface, it still relies upon another object to free it. The example returns: Creating TDelegateClass Creating TMyClass Creating TDelegateClass Destroying TMyClass Destroying TDelegateClass i.e. there is a missing call to the TDelegateClass destructor. This is because I created it standalone (in "DoRun) just to illustrate the point. There is a real need to update the FPC manual to include TContainedObject. It's importance for interface delegation and its limitations. How you implement interface delegation clearly has a big outcome on how the interface is used by the user. program project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp { you can add units after this }; type { TDelegateTest } TDelegateTest = class(TCustomApplication) protected procedure DoRun; override; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure WriteHelp; virtual; end; IMyInterface = interface procedure P1; end; { TDelegateClass } TDelegateClass = class(TContainedObject, IMyInterface) private procedure P1; public constructor Create(aController: IUnknown); destructor Destroy; override; end; { TMyClass } TMyClass = class(TInterfacedObject, IMyInterface) private FMyInterface: TDelegateClass; property MyInterface: TDelegateClass read FMyInterface implements IMyInterface; public constructor Create; destructor Destroy; override; end; { TDelegateClass } procedure TDelegateClass.P1; begin writeln('P1'); end; constructor TDelegateClass.Create(aController: IUnknown); begin inherited Create(aController); writeln('Creating ',ClassName); end; destructor TDelegateClass.Destroy; begin writeln('Destroying ',ClassName); inherited Destroy; end; { TMyClass } constructor TMyClass.Create; begin inherited Create; FMyInterface := TDelegateClass.Create(self); writeln('Creating ',ClassName); end; destructor TMyClass.Destroy; begin writeln('Destroying ',ClassName); if FMyInterface <> nil then FMyInterface.Free; inherited Destroy; end; { TDelegateTest } procedure TDelegateTest.DoRun; var Intf: IUnknown; Intf2: IMyInterface; begin Intf := TMyClass.Create; Intf2 := TDelegateClass.Create(Intf); {never destroyed} // stop program loop Terminate; end; constructor TDelegateTest.Create(TheOwner: TComponent); begin inherited Create(TheOwner); StopOnException := True; end; destructor TDelegateTest.Destroy; begin inherited Destroy; end; procedure TDelegateTest.WriteHelp; begin { add your help code here } writeln('Usage: ', ExeName, ' -h'); end; var Application: TDelegateTest; begin Application := TDelegateTest.Create(nil); Application.Title := 'Interface Delegation Test'; Application.Run; Application.Free; end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 8:29 AM, stdreamer wrote: > No! Delegation is a mechanism, when used, you have to know exactly how it > works. The "mechanism" here is about using [implements]. We have to know what is the sintaxe: - declare a property - use [implements] keyword - could be a class or interface - and so on. The user (programmer) that consumes these classes as a contained objects, should't know NOTHING about their hierarchies! > Delegation is only used to minimize code instead of writing a bunch > of procedures that call the contained object's methods. That's it and > nothing more. And this is great! As I know, only Object Pascal have this feature so, let's use it. > [...] > > The point is that you are trying to equate delegation with contained > objects/interfaces and that is not what delegates are about. Delegation has > nothing to do with the underlined mechanism you choose to use. > > Having said that, I have to agree with you that contained objects are the > most common supporting mechanism for a delegation and probably the most > logical to use. Delegates is about: pass the work for another. That's it. I can do that using only classical object composition. But Object Pascal have this cool feature that I can write less and the design is really good. So, I would like to use it. But if I need to know everty implementation for all my classes, to know if I can or not use as a "contained" or "aggregate" object... this is wrong. > As I said I do not see a rabbit hole that it was created by the compiler or > the language nor I think that the compiler should constrain you to one > mechanism. Really? Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 6:49 AM, Tony Whyman wrote: > The problem being referred to is the functionality described here: > > http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4 > > under the title "Interface delegation". The word "contained" does not appear > here. Maybe it should, but it doesn't. If TContainedObject does indeed solve > the problem then it would be useful to have it documented and, if so, for > interface delegation using a TInterfacedObject subclass to be at least > deprecated and may be even barred. > > The problem is that this is Rabbit Hole and it needs filling in otherwise > more will fall down it. In a Facebook group, called Delphi developer, Michal Mutl says: Also you can implement TIntegerValue as TIntegerValue = class(TAggregatedObject, IValue) and you can really take advantage of ARC (no Free call in TMyApp Destroy impl). But then you must use it only as delegate, not standalone (ExecuteIntegerValue will fail). I didn't know about TContainedObject or TAggregatedObject... these classes solve the problem? Maybe. But not so fast. I've implemeted a Lib and I would like to say to my team: — If you needs to implements an IStream interface, you can use delegates, just use the TDataStream class. The team shouldn't know about the hierarchy; about how was implemented these classes. They can use TDataStream directly or as a contained object. But as I understood, we need to use TContainedObject or TAggregatedObject only in these "special cases" I didn't test yet. I will. But if I'm right, ie, if TDataStream is inherited from TContainedObject and, because that, I can not use TDataStream as a simple instance, without a "root" object... well, this design is wrong. 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. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 7:30 AM, Tony Whyman wrote: > Reference Counted interfaces must be easy to use and should not require the > user to have advanced knowledge of how they work. If that last point is true > then all the that nay-sayers that argue against reference counted interfaces > have their point made for them. +1 Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Fri, Oct 7, 2016 at 6:31 AM, stdreamer wrote: > > Τhe problem of a contained interface has already been solved, see the > TContainedObject. To sum it up a contained object reference counting > mechanism increments and decrements the container's reference counter it > does not have a life of its own Nobody tell about TContainedObject until now... Maybe it should be documented on topic about delegates. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/2016 13:30 μμ, Tony Whyman wrote: On 07/10/16 11:08, stdreamer wrote: I see no rabbit hole or any other problem in the code posted so far except perhaps lack of proper clean up which might be intentional. A Rabbit Hole is not the same as a bug and my point is not that "interface delegation" does not work, it is that it is counter-intuitive and poorly documented to the point of undocumented. Your introduction of TContainedObject is just another example of missing information. No! Delegation is a mechanism, when used, you have to know exactly how it works. Delegation is only used to minimize code instead of writing a bunch of procedures that call the contained object's methods. That's it and nothing more. The contained object is something else that happens to be used in this example. Here is an other delegation with out a contained interface. interface TMyInteger = Class; IValue = interface ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}'] function AsString:string; end; IMyInterface = interface ['{5E04F587-E4A0-42A7-850C-74C882BB5958}'] procedure DoSomething; end; //tmyvalue can inherit from tContainedobject //for simplification. TMyValue = class(TInterfacedObject, IValue) private FSource :TMyInteger; public function AsString:String; constructor Create(aSource:TMyObject); end; //IValue must be part of TMyObject not a simple property. { TMyObject } { TMyInteger } TMyInteger = class(TInterfacedObject, IMyInterface, IValue) private FMyValue :variant; function GetValue :IValue; private property MyValue :IValue read GetValue implements IValue; public procedure DoSomething; end; implementation function TMyInteger.GetValue :IValue; begin Result := TMyValue.Create(Self); end; procedure TMyInteger.DoSomething; begin end; function TMyValue.AsString :String; begin result := ToString(FSource.FMyValue); end; constructor TMyValue.Create(aSource :TMyInteger); begin inherited; FSource := aSource; end; Reference Counted interfaces must be easy to use and should not require the user to have advanced knowledge of how they work.If that last point is true then all the that nay-sayers that argue against reference counted interfaces have their point made for them. Erm knifes are easy to use as well but cutting your self with one is your problem to solve. The point is that you are trying to equate delegation with contained objects/interfaces and that is not what delegates are about. Delegation has nothing to do with the underlined mechanism you choose to use. Having said that, I have to agree with you that contained objects are the most common supporting mechanism for a delegation and probably the most logical to use. As I said I do not see a rabbit hole that it was created by the compiler or the language nor I think that the compiler should constrain you to one mechanism. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/16 11:08, stdreamer wrote: I see no rabbit hole or any other problem in the code posted so far except perhaps lack of proper clean up which might be intentional. A Rabbit Hole is not the same as a bug and my point is not that "interface delegation" does not work, it is that it is counter-intuitive and poorly documented to the point of undocumented. Your introduction of TContainedObject is just another example of missing information. Reference Counted interfaces must be easy to use and should not require the user to have advanced knowledge of how they work. If that last point is true then all the that nay-sayers that argue against reference counted interfaces have their point made for them. A Rabbit Hole comes from Alice in Wonderland and when you fall down it you are not just chasing a White Rabbit, you have found yourself in another universe that has a different logic to your own. Reference counting with Interface Delegation seems to have a different logic to that of normal reference counted interfaces - and that is why you feel that you have fallen down a Rabbit Hole as soon as you start trying to use them. “But I don’t want to go among mad people," Alice remarked. "Oh, you can’t help that," said the Cat: "we’re all mad here. I’m mad. You’re mad." "How do you know I’m mad?" said Alice. "You must be," said the Cat, "or you wouldn’t have come here.” ― Lewis Carroll, Alice in Wonderland ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 07/10/2016 12:49 μμ, Tony Whyman wrote: You seem to be playing around with words. Perhaps I am guilty of sloppy English when I say "interface is copied" when meaning "an interface reference is copied". However, this does not change the underlying problem. The problem being referred to is the functionality described here: http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4 under the title "Interface delegation". The word "contained" does not appear here. As it should, contained interfaces are one way to solve the problem there are other ways that are design/domain specific and yet again there is the option(already given here) to use interface variables instead of object variables, just make sure you set them to null on the destructor to release the interface. I see no rabbit hole or any other problem in the code posted so far except perhaps lack of proper clean up which might be intentional. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
You seem to be playing around with words. Perhaps I am guilty of sloppy English when I say "interface is copied" when meaning "an interface reference is copied". However, this does not change the underlying problem. The problem being referred to is the functionality described here: http://freepascal.org/docs-html/current/ref/refse44.html#x98-127.4 under the title "Interface delegation". The word "contained" does not appear here. Maybe it should, but it doesn't. If TContainedObject does indeed solve the problem then it would be useful to have it documented and, if so, for interface delegation using a TInterfacedObject subclass to be at least deprecated and may be even barred. The problem is that this is Rabbit Hole and it needs filling in otherwise more will fall down it. On 07/10/16 10:31, stdreamer wrote: On 05/10/2016 19:13 μμ, Tony Whyman wrote: 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. I'm guessing that by "coerced" you mean "reference a contained interface". 2. When the interface is copied that reference count is again incremented. Interface can not be copied only implement objects can be copied and when they are their interface counter has nothing to do with the original interface, in fact it is the exact opposite, after a copy you need to make sure that the counter has been reset, which leads to believe that I misunderstood something. 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. That is not a delegated interface that is a contained interface. A delegated interface goes something like this IValue = interface ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}'] function AsString:string; end; IMyInterface = interface ['{5E04F587-E4A0-42A7-850C-74C882BB5958}'] procedure DoSomething; end; //tmyvalue can inherit from tContainedobject //for simplification. TMyValue = class(TInterfacedObject, IValue) function AsString:String; end; //IValue must be part of TMyObject not a simple property. TMyObject = class(TInterfacedObject, IMyInterface, IValue) private property MyValue :TMyValue implements IValue; end; Τhe problem of a contained interface has already been solved, see the TContainedObject. To sum it up a contained object reference counting mechanism increments and decrements the container's reference counter it does not have a life of its own. Sorry the rest look like a rabbit hole based on the wrong assumptions to me, there might be some merit but I have no will to search for it. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 05/10/2016 19:13 μμ, Tony Whyman wrote: 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. I'm guessing that by "coerced" you mean "reference a contained interface". 2. When the interface is copied that reference count is again incremented. Interface can not be copied only implement objects can be copied and when they are their interface counter has nothing to do with the original interface, in fact it is the exact opposite, after a copy you need to make sure that the counter has been reset, which leads to believe that I misunderstood something. 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. That is not a delegated interface that is a contained interface. A delegated interface goes something like this IValue = interface ['{72D8B44F-5834-425D-AB3A-45785E94E2E4}'] function AsString:string; end; IMyInterface = interface ['{5E04F587-E4A0-42A7-850C-74C882BB5958}'] procedure DoSomething; end; //tmyvalue can inherit from tContainedobject //for simplification. TMyValue = class(TInterfacedObject, IValue) function AsString:String; end; //IValue must be part of TMyObject not a simple property. TMyObject = class(TInterfacedObject, IMyInterface, IValue) private property MyValue :TMyValue implements IValue; end; Τhe problem of a contained interface has already been solved, see the TContainedObject. To sum it up a contained object reference counting mechanism increments and decrements the container's reference counter it does not have a life of its own. Sorry the rest look like a rabbit hole based on the wrong assumptions to me, there might be some merit but I have no will to search for it. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
Hi Graeme, On Thu, Oct 6, 2016 at 12:05 PM, Graeme Geldenhuys wrote: > Hello Marcos, > > On 2016-10-06 at 11:41, Marcos Douglas wrote: > >> The COM and CORBA names, are both wrong. >> When you say COM, everybody thinks on Windows... that sad. > > > Yes, both names are horribly inaccurate. Unfortunately I don't see FPC > developers rectifying that any time soon. :-/ +1 Unfortunately. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thu, Oct 6, 2016 at 11:57 AM, Graeme Geldenhuys wrote: > Hello Marcos, > > On 2016-10-06 at 11:25, Marcos Douglas wrote: > >> you need to declarate >> two variables to do one job. >> I don't like that and I think shouldn't be necessary. > > Well, to be fair, that example is not representative of a real-world > application. In a real-world app, I would not declare and release > objects and interface references like than - in the same procedure. Yes of course, I know. You will do some like that: constructor TFoo.Create; begin FTheObject := TBar.Create; // implements ITheObject end; destructor TFoo.Destroy; begin FTheObject.Free; end; procedure TFoo.Execute; begin CallSomethingThatAcceptsAnInterface(FTheObject); end; Nothing wrong. But you needs to create TFoo and manage it. Regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
Hello Marcos, On 2016-10-06 at 11:41, Marcos Douglas wrote: > The COM and CORBA names, are both wrong. > When you say COM, everybody thinks on Windows... that sad. Yes, both names are horribly inaccurate. Unfortunately I don't see FPC developers rectifying that any time soon. :-/ Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
Hello Marcos, On 2016-10-06 at 11:25, Marcos Douglas wrote: > you need to declarate > two variables to do one job. > I don't like that and I think shouldn't be necessary. Well, to be fair, that example is not representative of a real-world application. In a real-world app, I would not declare and release objects and interface references like than - in the same procedure. Regards, - Graeme - fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thu, Oct 6, 2016 at 7:36 AM, Graeme Geldenhuys wrote: > On 2016-10-06 02:49, Marcos Douglas wrote: >> I understand you, but reference counting help us to write a better >> code, more object-oriented. > > That's got nothing to do with reference counting functionality. I use > object-oriented coding practices all the time, but I don't need > reference counting for that. OOP, for me, It is closer to functional programming. You should to code more declarative and less imperative. Declare a variable; Create; try-finally; using line-by-line; call Free... that is imperative, Procedural and not about OOP. >> I'm using decorator pattern. No problem with it, but delegates makes >> me write less code and the design is awesome. > > So, nothing stops you from using interface delegates with CORBA style > interfaces. See the example code I just posted, where I converted the > original example to use CORBA style interfaces instead. I saw. But I can't use like that, as I explained above. Sorry... but thanks. > I'm a huge believer and user of design patterns, and most of them I've > implemented using Interfaces. Nothing there tells me I must use COM > style interfaces. The COM and CORBA names, are both wrong. When you say COM, everybody thinks on Windows... that sad. IMHO, interfaces with reference-counting is useful to write better code, less imperative and using a design more closer to functional. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thu, Oct 6, 2016 at 7:30 AM, Graeme Geldenhuys wrote: > On 2016-10-05 16:26, Marcos Douglas wrote: >> So, I coded a new example — more simpler, I think — to demonstrate the same >> problem and prove that there is some wrong that is causing a memleak. > > And here is that example converted to use CORBA style interfaces and no > memory leaks. I've used CORBA before... but see your example, you need to declarate two variables to do one job. I don't like that and I think shouldn't be necessary. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thu, Oct 6, 2016 at 7:11 AM, Graeme Geldenhuys wrote: > On 2016-10-06 02:34, Marcos Douglas wrote: >> But, the result was the same, even using D7. >> So, is this by design? Sad... > > Sad and nasty indeed. But it seems it is “by design” or done for “Delphi > compatibility”. > > It would be interesting to know what Delphi developers think of this. > You should post the new code example and message to a Delphi newsgroup > or Google+ forum and see what they think of that. If it has been around > since the D7 days (and maybe even earlier), they might have an > explanation or work-around for you. That's a good idea. I'll do it. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 06/10/16 11:08, Graeme Geldenhuys wrote: I've seem some COM Interface code where they had to resort to using raw Pointer types etc to try and avoid reference counting and causing unexpected memory leaks. I have also seen plenty of examples of poor coding with classes, but the fact that someone writes bad object oriented programs doesn't mean that object oriented is a poor programming technique. Likewise, poor programming using com interfaces doesn't invalidate the use of com interfaces. When you work with interfaces, there are two issues to consider: 1. How easy is the interface to use 2. How do you write the underlying classes. To me, the first rules out delegated interfaces and COM. Even advanced level programmers will get it wrong and you will never get an easy to use interface with this combination. It looks like a design error that came from Delphi and was copied by FPC. However, if you rule out this combination, COM does make for what seems to be a very intuitive easy to use interface, in the same way that AnsiStrings are easy to use. On the other hand, implementing the classes that provide a com interface does require some skill and is not for everyone. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-06 02:49, Marcos Douglas wrote: > I understand you, but reference counting help us to write a better > code, more object-oriented. That's got nothing to do with reference counting functionality. I use object-oriented coding practices all the time, but I don't need reference counting for that. > I'm using decorator pattern. No problem with it, but delegates makes > me write less code and the design is awesome. So, nothing stops you from using interface delegates with CORBA style interfaces. See the example code I just posted, where I converted the original example to use CORBA style interfaces instead. I'm a huge believer and user of design patterns, and most of them I've implemented using Interfaces. Nothing there tells me I must use COM style interfaces. > For me, it's a bug. Sorry. That I agree with. There seems to be a COM reference counted bug. Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-05 16:26, Marcos Douglas wrote: > So, I coded a new example — more simpler, I think — to demonstrate the same > problem and prove that there is some wrong that is causing a memleak. And here is that example converted to use CORBA style interfaces and no memory leaks. Program output: == [tmp]$ ./test.exe IntegerValue: TIntegerValue.Create Number is 5 TIntegerValue.Destroy MyApp: TIntegerValue.Create TMyApp.Create Number is 10 TIntegerValue.Destroy TMyApp.Destroy MyAppAsInterface: TIntegerValue.Create TMyApp.Create Number is 20 TIntegerValue.Destroy TMyApp.Destroy Heap dump by heaptrc unit 29 memory blocks allocated : 2045/2080 29 memory blocks freed : 2045/2080 0 unfreed memory blocks : 0 True heap size : 1409024 (32 used in System startup) True free heap : 1408992 == Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp program Project1; {$mode objfpc}{$H+} {$interfaces corba} uses Classes, SysUtils; type IValue = interface ['{C3151460-CA9B-447A-A7E8-86399222E844}'] function AsString: string; end; TIntegerValue = class(TObject, IValue) private FValue: Integer; public constructor Create(Value: Integer); destructor Destroy; override; function AsString: string; end; TMyApp = class(TObject, IValue) private FValue: TIntegerValue; function GetValue: IValue; // this interface property doesn't need to be public property Value: IValue read GetValue implements IValue; public constructor Create(AValue: Integer); destructor Destroy; override; end; { TIntegerValue } constructor TIntegerValue.Create(Value: Integer); begin inherited Create; FValue := Value; WriteLn('TIntegerValue.Create'); end; destructor TIntegerValue.Destroy; begin WriteLn('TIntegerValue.Destroy'); inherited Destroy; end; function TIntegerValue.AsString: string; begin Result := 'Number is ' + IntToStr(FValue); end; { TMyApp } function TMyApp.GetValue: IValue; begin Result := FValue; end; constructor TMyApp.Create(AValue: Integer); begin inherited Create; FValue := TIntegerValue.Create(AValue); WriteLn('TMyApp.Create'); end; destructor TMyApp.Destroy; begin FValue.Free; WriteLn('TMyApp.Destroy'); inherited Destroy; end; // Program procedure ExecuteIntegerValue; var i: TIntegerValue; V: IValue; begin WriteLn; WriteLn('IntegerValue:'); i := TIntegerValue.Create(5); V := i; WriteLn(V.AsString); i.Free; end; procedure ExecuteMyApp; var App: TMyApp; begin WriteLn; WriteLn('MyApp:'); App := TMyApp.Create(10); try WriteLn(App.Value.AsString); finally App.Free; end; end; procedure ExecuteMyAppAsInterface; var app: TMyApp; V: IValue; begin WriteLn; WriteLn('MyAppAsInterface:'); try app := TMyApp.Create(20); V := app; WriteLn(V.AsString); finally app.Free; end; end; begin ExecuteIntegerValue; ExecuteMyApp; ExecuteMyAppAsInterface; ReadLn; end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-06 02:34, Marcos Douglas wrote: > But, the result was the same, even using D7. > So, is this by design? Sad... Sad and nasty indeed. But it seems it is “by design” or done for “Delphi compatibility”. It would be interesting to know what Delphi developers think of this. You should post the new code example and message to a Delphi newsgroup or Google+ forum and see what they think of that. If it has been around since the D7 days (and maybe even earlier), they might have an explanation or work-around for you. Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-05 23:16, Tony Whyman wrote: > Used properly reference counted interfaces are very powerful and allow > for some very elegant programming. Do you complain about AnsiStrings? I have very powerful and elegant programming with CORBA interfaces too. ;-) Also as Martin mentioned, reference counting works wonders in simple cases, but gets very nasty in medium to complex cases. I've seem some COM Interface code where they had to resort to using raw Pointer types etc to try and avoid reference counting and causing unexpected memory leaks. No such problems with CORBA Interfaces. ps: You can obviously implement your own reference counted CORBA interface for the simple cases too. So you have the best of both worlds I guess, but when using CORBA Interfaces, I would avoid mixing reference counted and non-reference counted interfaces. Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-06 05:54, Martin Schreiber wrote: > Recently I had to revive my stone old AMD-K6 PC with Windows 95. What marvel, > that relict with its age-old applications provides a better user experience, > is snappier, more convenient and more productive than my newest Linux machine > with the modern desktops and applications. We seem to have a lot in common. I still prefer Win2000 for any Windows development (if I must use Windows). Memory efficient and very snappy indeed! For Linux (actually FreeBSD) I long ago gave up on the extremely bloated 'desktop environments' and have for years been using JWM (Joe's Window Manager) - old school to the point, extremely fast and memory efficient (8MB max) window manager. JWM stays out of my way, has hardly any keyboard shortcuts to interfere with my daily programs, gives me a task bar, virtual desktops and a popup menu. I don't need more than that. Oh, and I run this on a Intel i7 3.5Ghz CPU with 32GB RAM. I prefer to use my RAM for actual applications, VMs or the ZFS file system - not the desktop environment. ;-) Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Thursday 06 October 2016 00:16:22 Tony Whyman wrote: > On 05/10/16 23:03, Graeme Geldenhuys wrote: > > Martin Schreiber recently mentioned in another Interface discussion that > > there is a very good reason he doesn’t use COM style interfaces… > > Reference Counting! > > Used properly reference counted interfaces are very powerful and allow > for some very elegant programming. Do you complain about AnsiStrings? > They are reference counted. Would you really want to have to free every > string explicitly? Dynamic arrays are similarly reference counted. > Reference counting is great for simple types like strings and dynamic arrays but is a nightmare with the venturesome mixture of COM-interface and classes from Delphi. Even reference counting for complex classes is no good idea IMO, I fear the times when FPC will implement ARC. I don't think that a programming language should hide more and more of the internal working of the code he writes from the programmer. Take a look at the modern C++ programs; the LLVM-compiler is a good example. It is horrific slow. Stepping through the code shows that there are complex multi-level dynamic type conversion and dataaccess routines at almost every statement. The typical C++ programmer does not need to care about because the programming language takes care for the boring tasks. The typical C++ programmer actually *does* not care about performance because competing programs are not faster; they are written in a modern programming language too... Recently I had to revive my stone old AMD-K6 PC with Windows 95. What marvel, that relict with its age-old applications provides a better user experience, is snappier, more convenient and more productive than my newest Linux machine with the modern desktops and applications. Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Wed, Oct 5, 2016 at 7:16 PM, Tony Whyman wrote: > > Reference counted interfaces allow you to create classes (and objects) that > behave in the same way as AnsiStrings. IMHO, a lot of standard packages > would be greatly improved if they used com interfaces. I agree with you 100%. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Wed, Oct 5, 2016 at 7:07 PM, Tony Whyman wrote: > >[...] > > No, if you explicitly free the provider class there will be no memleaks. My > point is that having to do this is counter-intuitive and easy to get wrong > - or to overlook cases where it is necessary. That is it, counter-intuitive and easy to get wrong. Another thing easily to forget and get memleaks is not get the result of constructors. For example. Consider this: function TFoo.Execute(const Name: string): string; begin Result := TAction.Create(TTask.Create(Name)).Execute.ToString; end; - TTask is a class that takes a string in the constructor; - TTask implements ITask, an interface; - TAction is a class that receives an ITask interface in the constructor; - TAction implements IAction, an interface; - TAction has an Execute method that returns an IResult, an interface; - IResult has a ToString method that returns the result in string format; How many memory leaks we have here? 0, 1 or 2? The answer is 1. So, we need to declare an variable: function TFoo.Execute(const Name: string): string; var A: IAction; begin A := TAction.Create(TTask.Create(Name)); Result := A.Execute.ToString; end; Verbose and unnecessary, in my opinion. Sometimes I forget to declare a variable, sometimes not... this is unproductive! So, I created my own "design pattern" that I called: New Method. The refactored code is: function TFoo.Execute(const Name: string): string; begin Result := TAction.New(TTask.New(Name)).Execute.ToString; end; I explained here http://objectpascalprogramming.com/posts/interfaces-e-o-metodo-estatico-new/ but you need to translate. >> I understood you but I can't help, because I don't know how the >> compiler works to do this 'kind of magic' — I think only Object Pascal >> has delegation in that way, right? > > Here I was suggesting a compiler change (bug fix?) +1 >> Delegates is a powerful feature. I can write less and compose complexy >> objects using delegation. Really cool. >> >> We need to compare with Delphi? >> I don't have it, but I guess this problem there isn't there. > > I never used delegated interfaces in Delphi. In FPC I try to avoid them > given the problems you get. On the other hand, reference counted com > interfaces are a great feature and it's a pity delegated interfaces are so > awkward. I agree. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Wed, Oct 5, 2016 at 7:03 PM, Graeme Geldenhuys wrote: > Martin Schreiber recently mentioned in another Interface discussion that > there is a very good reason he doesn’t use COM style interfaces… > Reference Counting! I understand you, but reference counting help us to write a better code, more object-oriented. > Stick with CORBA style interfaces and things work much simpler. I have > to agree. I’ve used CORBA style interfaces for years with great success > and no memory leaks. You get all the benefits of Interfaces, but without > the Reference Counting troubles and complexities. If you really are > writing COM (Windows specific) applications, then fine — otherwise use > CORBA style interfaces. Simplicity. I think that's depends on point of view. Today I write a better code than 3~4 years ago. For me it's much more simpler: - no more .Free - no more try-finally (to use .Free) - no inheritance - less variables and types declarations - more functional design I'm using decorator pattern. No problem with it, but delegates makes me write less code and the design is awesome. None language has the same feature, as far as I know. We have it, but doesn't work... well, doesn't work in all cases, in all possibilities. For me, it's a bug. Sorry. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On Wed, Oct 5, 2016 at 6:51 PM, Graeme Geldenhuys wrote: > On 2016-10-05 16:26, Marcos Douglas wrote: >> Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1 >> i386-win32-win32/win64) > > Just so you know... bug or not, it seems to have the same behaviour as > with Delphi 7. Compiled with D7 it has the exact same output. In fact, > compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it. > [...] > Ignore that bit... Looking at the code in detail I see there was a > ReadLn statement at the end. Dope! :) But, the result was the same, even using D7. So, is this by design? Sad... Regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 05/10/16 23:03, Graeme Geldenhuys wrote: Martin Schreiber recently mentioned in another Interface discussion that there is a very good reason he doesn’t use COM style interfaces… Reference Counting! Used properly reference counted interfaces are very powerful and allow for some very elegant programming. Do you complain about AnsiStrings? They are reference counted. Would you really want to have to free every string explicitly? Dynamic arrays are similarly reference counted. Reference counted interfaces allow you to create classes (and objects) that behave in the same way as AnsiStrings. IMHO, a lot of standard packages would be greatly improved if they used com interfaces. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 05/10/16 19:19, Marcos Douglas wrote: Hi Tony, On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman wrote: [...] 7. You are responsible for freeing the object that "provides" the delegated interface. But I'm working only using Interfaces. All variables are interfaces type. So, I can't free the object myself. As I understand it, it depends on the variable to which the object is first assigned. For example: TMyClass = class(TInterfacedObject,IUnknown); var Obj: TMyClass; {Note the var is of type TMyClass} begin Obj := TMyClass.Create; try ... finally Obj.Free; {This is OK and necessary} end end; Alternatively: var Obj: IUnknown; begin Obj := TMyClass.Create; try ... finally Obj.Free; {Not required and will cause an exception when obj goes out of scope} end end; 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. I disagree. Well, works, but with memleaks... so, I can't have a real program on the server with memleaks. No, if you explicitly free the provider class there will be no memleaks. My point is that having to do this is counter-intuitive and easy to get wrong - or to overlook cases where it is necessary. 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. I understood you but I can't help, because I don't know how the compiler works to do this 'kind of magic' — I think only Object Pascal has delegation in that way, right? Here I was suggesting a compiler change (bug fix?) Delegates is a powerful feature. I can write less and compose complexy objects using delegation. Really cool. We need to compare with Delphi? I don't have it, but I guess this problem there isn't there. I never used delegated interfaces in Delphi. In FPC I try to avoid them given the problems you get. On the other hand, reference counted com interfaces are a great feature and it's a pity delegated interfaces are so awkward. What do you think? Best regards, Marcos Douglas On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman wrote: 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
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-05 16:26, Marcos Douglas wrote: > So, I coded a new example — more simpler, I think — to demonstrate the same > problem and prove that there is some wrong that is causing a memleak. Martin Schreiber recently mentioned in another Interface discussion that there is a very good reason he doesn’t use COM style interfaces… Reference Counting! Stick with CORBA style interfaces and things work much simpler. I have to agree. I’ve used CORBA style interfaces for years with great success and no memory leaks. You get all the benefits of Interfaces, but without the Reference Counting troubles and complexities. If you really are writing COM (Windows specific) applications, then fine — otherwise use CORBA style interfaces. Just my 2¢ worth. Regards, Graeme -- fpGUI Toolkit — a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-05 22:51, Graeme Geldenhuys wrote: > In fact, > compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it. Ignore that bit... Looking at the code in detail I see there was a ReadLn statement at the end. Dope! :) Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
On 2016-10-05 16:26, Marcos Douglas wrote: > Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1 > i386-win32-win32/win64) Just so you know... bug or not, it seems to have the same behaviour as with Delphi 7. Compiled with D7 it has the exact same output. In fact, compiled with Delphi 7, the app doesn't quit at all. I had to Ctrl+C it. c:\Programming\test\interface_delegation_delphi>project1.exe IntegerValue: TIntegerValue.Create Number is 5 TIntegerValue.Destroy MyApp: TIntegerValue.Create TMyApp.Create Number is 10 TMyApp.Destroy TIntegerValue.Destroy MyAppAsInterface: TIntegerValue.Create TMyApp.Create Number is 20 ^C c:\Programming\test\interface_delegation_delphi> Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
Hi Tony, On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman wrote: > > [...] > > 7. You are responsible for freeing the object that "provides" the delegated > interface. But I'm working only using Interfaces. All variables are interfaces type. So, I can't free the object myself. > 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. I disagree. Well, works, but with memleaks... so, I can't have a real program on the server with memleaks. > 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. I understood you but I can't help, because I don't know how the compiler works to do this 'kind of magic' — I think only Object Pascal has delegation in that way, right? Delegates is a powerful feature. I can write less and compose complexy objects using delegation. Really cool. We need to compare with Delphi? I don't have it, but I guess this problem there isn't there. What do you think? Best regards, Marcos Douglas On Wed, Oct 5, 2016 at 1:13 PM, Tony Whyman wrote: > 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 > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
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 ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
[fpc-pascal] A serious Memleak using delegates/implements (was: Delegate Interface class does not seem to be referenced counted)
Hi, 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. So, I coded a new example — more simpler, I think — to demonstrate the same problem and prove that there is some wrong that is causing a memleak. === BEGIN CODE === program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils; type IValue = interface function AsString: string; end; TIntegerValue = class(TInterfacedObject, IValue) private FValue: Integer; public constructor Create(Value: Integer); destructor Destroy; override; function AsString: string; end; TMyApp = class(TInterfacedObject, IValue) private FValue: IValue; public constructor Create(Value: Integer); destructor Destroy; override; property Value: IValue read FValue implements IValue; end; { TIntegerValue } constructor TIntegerValue.Create(Value: Integer); begin inherited Create; FValue := Value; WriteLn('TIntegerValue.Create'); end; destructor TIntegerValue.Destroy; begin WriteLn('TIntegerValue.Destroy'); inherited Destroy; end; function TIntegerValue.AsString: string; begin Result := 'Number is ' + IntToStr(FValue); end; { TMyApp } constructor TMyApp.Create(Value: Integer); begin inherited Create; FValue := TIntegerValue.Create(Value); WriteLn('TMyApp.Create'); end; destructor TMyApp.Destroy; begin WriteLn('TMyApp.Destroy'); inherited Destroy; end; // Program procedure ExecuteIntegerValue; var V: IValue; begin WriteLn; WriteLn('IntegerValue:'); V := TIntegerValue.Create(5); WriteLn(V.AsString); end; procedure ExecuteMyApp; var App: TMyApp; begin WriteLn; WriteLn('MyApp:'); App := TMyApp.Create(10); try WriteLn(App.Value.AsString); finally App.Free; end; end; procedure ExecuteMyAppAsInterface; var V: IValue; begin WriteLn; WriteLn('MyAppAsInterface:'); V := TMyApp.Create(20); WriteLn(V.AsString); end; begin ExecuteIntegerValue; ExecuteMyApp; ExecuteMyAppAsInterface; ReadLn; end. === END CODE === Here is the output on my machine (Lazarus 1.7 r52880M FPC 3.0.1 i386-win32-win32/win64) === BEGIN OUTPUT === W:\temp>project1.exe IntegerValue: TIntegerValue.Create Number is 5 TIntegerValue.Destroy MyApp: TIntegerValue.Create TMyApp.Create Number is 10 TMyApp.Destroy TIntegerValue.Destroy MyAppAsInterface: TIntegerValue.Create TMyApp.Create Number is 20 Heap dump by heaptrc unit 83 memory blocks allocated : 2017/2200 81 memory blocks freed : 1981/2160 2 unfreed memory blocks : 36 True heap size : 229376 (80 used in System startup) True free heap : 229104 Should be : 229128 Call trace for block $01812928 size 20 $004017DA TMYAPP__CREATE, line 59 of W:/temp/project1.lpr $00401B82 EXECUTEMYAPPASINTERFACE, line 101 of W:/temp/project1.lpr $00401C08 main, line 108 of W:/temp/project1.lpr Call trace for block $018128C8 size 16 $00401B82 EXECUTEMYAPPASINTERFACE, line 101 of W:/temp/project1.lpr $00401C08 main, line 108 of W:/temp/project1.lpr W:\temp> === END OUTPUT === As you can see, the problem occurs just in the last test, when the classe TMyApp is used as an instance of the interface IValue. I don't know if this problem was solved on trunk. I would like to know. If not solved, I will open an issue. Best regards, Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal