Where should a class free its private variables? - delphi

As there is no garbage collection in Delphi, where exactly do you unload variables?
Say I have a type with a set of private vars.
Would it suffice to have a Destroy method that does this work?
Do I need to explicitly call this destroy method in my consuming classes?

The best way to organize destruction in delphi is to always think about "who will create the given vars".
If you also free them in this context (For you private vars the destroy method of the class) it's much less likely that you will encounter memory leaks.
Actually the destructor of a class is normally not called via
myInstance.Destroy();
instead the typical way of doing it is via
FreeAndNil(myInstance);
or
myInstance.Free();
As delphi will handle calling the destructor method at order

Objects need to be destroyed when you are ready with them: using .Free (which calls the destructor .Destroy) or FreeAndNil.
If you are using interfaces: they are reference counted and hence they are freed for you. The same for strings.
Most functions that you need to pass an object do not take ownership of the object so you should free it afterwards when you are done with them. If you create components on a form, please note that they are objects, are owned by the form and you should let the form free them for you.
For example: in your TLight you create a TTimer probably without an owner. In this case you should Free the timer in the destructor of the TLight class. If your TLight was a TControl or TComponent itself you could have created the Timer with Self as the Owner and it was automatically freed when your TLight instance was freed.

That's how I see it:
Primitive types (like integer, real, double, extended), arrays, sets, records: they are automatically destroyed when out of scope.
Reference-counted types (strings, interfaces types, interface references): they are automatically destroyed when their reference counter is equal to zero.
Objects from classes that fall in one of those situations: does not descend from TComponent, are in list objects that do not implement ownership or are a TComponent descendant but does not have an owner assigned to it:
When their class descend from TInterfacesObject and are accessed from a interface reference: same behavior from reference-counter types (see above)
Other cases: call Object.Free or FreeAndNil(Object) to manually destroy it (in a try..finally structure would be even better)
Objects that have an owner (TComponent descendants or are in list objects that implement ownership): the owner will take of them in proper time.
I noticed the following comment from OP:
I have noticed the concept of owner.
Yet I couldn't pass my custom class to
the TTimer.Create() method as it is
expecting a TComponent. Why do they
restrict things to be used in forms
only? Doesn't that furhter petrify the
bad habit of putting logic in your
views (forms)?
See, a TComponent descendant can be registered on the pallete to have the ability to be used in design-time (for example, in a form) . But it's doesn't means it must!!
You can pass your custom-class to TTimer.Create() if it descends from TComponent but you don't need to instantiate it in design-time - or even be owned by a TForm descendant (if you want to manage it's lifetime, you don't even need an owner!).
Ownership is a mechanism it's to help people to save time....

You keep referring to a "type with private vars" and asking about "unloading variables." I'm going to go out on a limb (as I may be have misinterpreted your message), and presume you're talking about class variables and are asking about when these class variables should be finalized when the "class unloads." (You've been doing Java or .NET programming at some point, no ;-).
The key to what you're asking is a unit finalization section. The overall layout of a unit includes 4 overall sections, two of which are optional, initialization and finalization.
unit Foo;
interface
// put things here you want other units to see
implementation
// put the *implementation* of the things from the interface here along with things
// you only want this unit to see.
initialization
// <optional> put code here that you want to execute when this unit is "loaded"
finalization
// <optional> put code here that you want to execute when this unit is "unloaded"
end.
If you're talking about instance variables of a class type, then some of the other answers you've already gotten (and are bound to get) should shed some light on that.

Related

Reference counted TList<T> vs TObjectList<T>

Can anyone point me toward tutorials or best practice for using object interfaces in a TList?
I started implementing this model to take advantage of the reference counting as an alternative to TObjectList (that I use extensively). While I had no problems implementing the list it appears that doing this adds complexity in other ways.
Specifically because the list is only holding an interface I don't have access to the class fields (obvious). So I end up littering the code with "MyInterface as TMyClass" or creating a lot of functions to access the fields. Is there some trick that I am not aware of that makes an interface container more usable?
If you need to access certain methods, why are you hiding them with interfaces? An interface is just that: A description of the ways that others can interact [interface] with that object: If you want other classes to interact with your class as an interfaced object, those methods should be part of the interface.
Using an interface as a shortcut to simplify finalization and then hacking it with casting violates the entire concept of interfaces, and can also cause memory leaks and hard to track down AV's, because of the way you are mixing your references: sometimes interface, sometimes TObject.
Can anyone point me toward tutorials or best practice for using object
interfaces in a TList?
Your problem has nothing to do with TList. All TList does is hold references to your objects, however they are designed - it knows nothing about the specifics of your object's interface or implementation. Your problem is that you are not designing your classes and interfaces correctly, as #ArnaudBouchez has pointed out in the comments.
I started implementing this model to take advantage of the reference
counting as an alternative to TObjectList (that I use extensively)
Why is that necessary? To simplify finalization? TObjectList owns its objects by default. (And you can also set the OwnsObjects property ) . You don't need to use interfaces to automate your clean-up if you're using TObjectList. You just have to free the TObjectList instance, just as you have to free a TList. Unless you need interfaces for a specific reason, using Objects and TObjectList is arguably preferable, since as opposed to interfaces, your finalization is deterministic.
From XE Help:
Create TObjectList instance.
This overloaded method creates a TObjectList instance.
The OwnsObjects parameter is a boolean that indicates whether object
entries are owned by the list. If the object is owned, when the entry
is removed from the list, the object is freed. The OwnsObjects
property is set from the value of this parameter. The default is true.
When you free TObjectList, the objects are also deallocated when OwnObjects=True. See:
Clear a TList or a TObjectList (accepted answer there)
Know: Normally there is no reason for you as a Delphi developer to get involved at all with details of reference counting. If you feel you need to do so, something is wrong with your design at the fundamental level. Reference counting is implemented in TInterfacedObject, and works transparently. All of your Delphi interfaced objects should be derived from TInterfacedObject (or one of its sibling or derivative classes), as follows:
interface
...
type
IMyInterface=interface (IUnknown)
[GUID]
function GetValue:integer;
end;
TMyInterface=class(TInterfacedObject,IMyInterface)
protected
function GetValue:integer;
end;
implementation
...
TMyInterface.GetValue:integer;
begin
result := fValue;
end;
end.
Then use it like this:
procedure useValue;
var im:IMyInterface;
x:integer;
begin
im:=TMyInterface.create;
x:=im.GetValue;
showMessage(inttstr(x));
end;
When useValue returns, im is cleaned up - you don't have to do anything or worry about reference counting. TInterfacedObject takes care of all that.
Note that in useValue, you declare the reference as IMyInterface but call the class constructor for TMyInterface - that is how you must initialize the interface - an interface has no constructor. However, since your reference type is IMyInterface, that is how it is treated by the compiler - only methods exposed through IMyInterface will be accessible.

How to change the parent class of an inherited class at runtime in Delphi?

Hi I'm developing a TControl descendant, lets name it THTMLBaseControl, at runtime that control only generates and output HTML code based on the settings of that control, so all the additional properties of the base TControl class and methods, including Windows Messaging system is really not used at runtime and causes memory overhead.
I need that control to be inherited from TControl so at design time I can use all the IDE designer stuff.
But at runtime almost all of those properties that at desingtime are needed i dont need them.
I also have all my controls inherited from that THTMLBaseControl, so creating a wrapper class per control class is not an option because it will duplicate the code a lot.
So what i need is something that at runtime, before the class is instantiated I can change the parent class so it will be instantiated based on another TControl-like class, maybe named TmyBaseControl inherited from "TComponent" as TControl Does, but that will not have all that TControl memory overhead and will only have the properties and methods needed by my THTMLBaseControl.
I really dont have a GUI at rutime is a web server that will serve only HTML, is some thing that intraweb and Raudus do, but always the issue is that all are based on TControl, so they have to be created at run time and generate a lot memory and process overhead that is not used. and maybe there could a solution so any THTMlBaseControl descendant instantiated at runtime will inherit the all properties and methods from TmyBaseControl and not from TControl.
I have seen there are ways to hack the VMT but maybe there are other solution and have not seen it. I already done changing the NewInstance, ClassParent and TnstanceSize class methods but i have to specify from which class and obviously i have to do the same steps per each inherited THTMLBaseControl class
And for the sake of all:
This is just a doubt, I need the components to be controls like TEdit, TPanel, visible and editable by the designer IDE I even could create my own TControl class but I was just thinking if I can reuse the code already existing.
Regards
You cannot change the class a run time. Once an object is instantiated, its class is fixed. You could hack the object to change its VMT pointer, making it refer to a different class, but that would still not address your main concern, which is memory usage — even if you change the VMT pointer, all the memory for the object has already been allocated; changing the VMT pointer doesn't magically make the object occupy less memory.
The first thing you could do is stop descending from TControl. As you've noted, you don't need any of the things it provides. All you want is something you can drop on a form at design time to set its properties. For that, all you need is TComponent, so make that your base class instead of TControl. Then you'll get something more like TTimer, which has no GUI. Once you've done that, you no longer need TForm, either. Instead, you can put your component on a TDataModule, which is specifically designed for managing non-visual components at design time.

Delphi - Accessing Object Instance Data from Another Object

I have my main form. Form_Main
It creates two instances of two classes.
Candle_Data : TCandle_Data;
Indicator_2700 : TIndicator_2700;
In order for Indicator_2700 to properly compute its values it must have access to the candle data in the obect Candle_Data from inside one of its methods. Thus how can Indicator_2700 access data inside Candle_Data? Does Form_Main have to pass it as a argument at Constructor time?
Both Class declarations are in their own unit file.
You could use any of the following (non-exhaustive) methods:
Pass the object reference as a parameter to any methods that need it. Of course you need to get hold of Candle_Data so the suitability of this approach really depends who the caller is.
Pass the Candle_Data object reference to the constructor of the other object and then store it in a private member field.
Make the object reference a public property of the single instance of the main form and access it that way.
We don't really have enough information to advise you which is best but the starting point is always to prefer parameters and local variables over global state.
TIndicator_2700 could have a property to link it to the instance of TCandle_Data that is relevant to its own instance or you should supply it as an argument to the method that needs to access the data.
You could certainly pass the TCandle_Data instance into the constructor of Indicator_2700, and store a reference within the resulting instance until you needed it.
Both class declarations are in their own unit file.
That suggests that both have nothing to do with the other. But still you want one to have knowledge about the other. It sounds like a little design mixup, but that doesn't need to be the case.
There are multiple solutions, here are three of them, each with its own purpose:
Place both classes in the same unit, only if both classes have a common theme/subject (e.g. TCar and TAirplane in the unit Transport),
Use one unit in the other unit, only if both units represent different subjects, but one may depend on the other (e.g. unit Transport uses unit Fuel: TCar needs TDiesel, but TDiesel doesn't need a TCar). This only works one-way. Delphi prevents using in both ways with a compiler error: "Circular unit reference to 'Fuel'". The only workaround is to use the second unit in the implementation section, but that usually is considered a big nono.
Declare a new base-class in a new unit, only if the base-class has a common subject, but the final descendants do not (e.g. TFuel is used by all transportation classes like TCar, TAirplane and THorse, but TFood (a descendant of TFuel) is only used by THorse and TPerson).
As for how to link both classes together, see the already given answers.

Stop client code from freeing shared objects in Delphi

I have implemented the FlyWeight pattern in my Delphi application. Everything has worked great, everything is a lot faster and takes less memory, but there is one thing I am worried about.
My implementation will only work as long as client code never calls Free() on the shared objects. In the Flyweight pattern, the FlyweightFactory itself is supposed to "maintain a reference to flyweights" i.e. to the shared objects.
My problem is that there is no (obvious) way to stop other code from destroying the objects once they have a reference. I could live with this, but it would be a "big win" if I could pass these objects round freely without worrying about accidental freeing.
To show a (contrived) example:
flyweight1:=FlyweightFactory.GetFlyweight(42);
WriteLn('Description is '+flyweight.Description);
flyweight1.Free;
flyweight2:=FlyweightFactory.GetFlyweight(42);
WriteLn('Description is '+flyweight.Description);
// Object has already been Freed!; behaviour is undefined
I have considered overriding the destructor as shown here to stop the flyweight object being freed altogether. This is not an option in my case as
a) I only want to stop cached objects from being Freed, not objects that aren't part of the cache. There is a lot of legacy code that doesn't use the cache; they still need to create and free objects manually.
b) I do want the FlyweightFactory to Free the objects during finalization; I agree with Warren P that a "zero leaked memory" policy is best.
I'll leave with a quote from the Flyweight chapter of GoF
Sharability implies some form of
reference counting or garbage
collection to reclaim storage when
it's no longer needed. However,
neither is necessary if the number of
flyweights is fixed and small. In that
case, the flyweights are worth keeping
around permanently.
In my case the flyweights are "fixed" and (sufficiently) small.
[UPDATE See my answer for details of how I solved this problem]
My answer to the question you link to still applies. The objects must know by means of a private boolean flag that they are cached objects. Then they can elect not to destroy themselves in Destroy and FreeInstance. There really is no alternative if you want to allow Free to be called.
To deal with finalization you would want to add the cached objects to a list of cached objects. That list of objects can be freed at finalization time. Of course the flag to disable freeing would have to be reset whilst you walked the list.
Having made this point regarding finalization, I would advise you to register an expected memory leak and just leak this memory. It makes the code much simpler and there's nothing to lose. Any memory you don't free will be reclaimed by the OS as soon as your executable closes. One word of caution: if your code is compiled into a DLL then leaking could be troublesome if your DLL is loaded, unloaded, loaded again etc.
What all this is telling you is that you are swimming against the current. Is it possible that you could achieve your goals with a different solution that fitted better with the way Delphi is steering you?
I suggest to add a reference count in order to known if your shared object is still used.
Every client should use the pattern AddRef / Release (AddRef increases the count; Release decrements it; if count reaches zero Free is called)
The AddRef may be called directly by your GetFlyweight method; Release has to be used instead of Free.
If you refactor your class and extract an interface from it the AddRef/Release pattern in naturally implemented in then interface implementation. (You could derive from TInterfacedObject or implement IInterface by your self)
Ideally you seldom want 2 ways of using the same things. It just complicates matters in the long run. In 6 months time, you might not be sure whether a particular piece of code is using the new flyweight paradigm or the old paradigm.
The best way to prevent someone calling Free or Destroy is to make sure it's not even there. And within the Delphi world, the only way to do that is to use interfaces.
To expand on your contrived example:
type
TFlyweightObject = class
public
constructor Create(ANumber: Integer);
function Description: string;
end;
TFlyweightFactory = class
public
function GetFlyweight(ANumber: Integer): TFlyweightObject;
end;
This being an object can easily be destoyed by a rogue client. You could make the following changes:
type
IFlyweight = interface
//place guid here
function Description: string;
end;
TFlyweightObject = class(TInterfacedObject, IFlyweight)
public
constructor Create(ANumber: Integer);
function Description: string;
end;
TFlyweightFactory = class
public
function GetFlyweight(ANumber: Integer): IFlyweight;
end;
Now any code that is updated to use the flyweight paradigm is forced to use it as intended. It's also easier to recognise the old code that still needs to be refactored because it doesn't use the interface. Old code would still construct the "flyweight" object directly.
You could also hide a destructor by making it protected or private. Programmers won't see it outside the scope of the unit in which it is declared in.
But I am posting this answer more like a curiosity because this will not prevent freeing an object by using FreeAndNil or by using a "Protected Hack"
I managed to get around the problems I cited in my original question using the following techniques, suggested by David Heffernan in his answer.
a) I only want to stop cached objects
from being Freed, not objects that
aren't part of the cache. There is a
lot of legacy code that doesn't use
the cache; they still need to create
and free objects manually.
I fixed this by subclassing the Flyweight class and overriding destroy, BeforeDestruction and FreeInstance in the subclass only. This left the parent class as is. The cache contains instances of the subclass (which can't be freed), whereas objects outside the cache can be freed as per usual.
b) I do want the FlyweightFactory to
Free the objects during finalization;
I agree with Warren P that a "zero
leaked memory" policy is best.
To solve this, I added a private boolean flag that has to be set to true before the object can be freed. This flag can only be set from the Cache Unit, it is not visible to other code. This means that the flag cannot be set outside by code outside the cache.
The destructor just looks like this:
destructor TCachedItem.destroy;
begin
if destroyAllowed then
inherited;
end;
If client code trys to Free a cached object, the call will have no effect.

If everything implemented an interface, would this be garbage collection?

I'm still something of a newbie, and I know my thinking is incorrect; I just don't know where ...
Just about everything in Delphi is descended from TObject. What if everything instead descended from a TInterfaceObject that implemented some trivial interface (e.g., "INamable," with a single method that returned a class's name string)? Since TObject already has a property that returns a name string, you wouldn't need to add anything to additional classes.
In other words, a TInterfacedObject would inherit from TObject (or something high up in the hierarchy), and everything currently descending from TObject would now descend from this new class. Wouldn't this mean everything was now reference counted?
If you can spot where my knowledge is lacking, I'd love to learn. Thanks, as always -- Al C.
It's not clear whether you're asking:
Why didn't Borland do this, when they originally developed Delphi?
Why don't Embarcadero do this, in a future version of Delphi?
Why don't I do this, with my own user data types?
Wouldn't this mean everything was now reference counted?
Yes it would.
However, you don't necessarily want everything to be ref-counted: every little integer, every string, every boolean, every element in an array ... if for no other reason that the implementation of ref-counting adds some overhead, e.g. a little extra memory per object, perhaps insignificant for large objects but proportionally more significant if applied to every tiny object.
Also, see also Garbage Collector For Delphi Objects and Components which says (quote),
Delphi provides three ways of object management :
Create/destroy the objects using try..finally.
Use TComponent descendants - create a component and let its owner free it.
Interfaces - when the reference count for an interface becomes 0 the
object which implements it is
destroyed.
The Delphi help says you shouldn't mix
the TComponent owner approach with the
interface memory management, but ...
Would this be garbage collection?
Not quite; mere reference-counting isn't as robust as garbage-collection:
With reference-counting, if you have two reference-counted instances each holding a reference to the other, then they're not released automatically. To release them you would need to break this 'circular reference' (i.e. explicitly tell one of them to release its reference to the other).
With true garbage-collection, the garbage-collector would notice that those two istance aren't referenced from anywhere else, and release them both.
Update
If you annotate your potentially circular references as [weak] references, then they will get destroyed ok. But prior to Delphi 10.1 Berlin this only works in the NexGen compilers (i.e. those that use LLVM under the hood). From 10.1 Berlin onwards these [weak] references work everywhere.
It wouldn't be working garbage collection because interfaces use a very simple reference-counting system, and circular references, which are very common in Delphi code, break simple ref-counting.
No, because of two things:
Even if a class implements an interface it does not automatically make it reference counted. Only if you actually use it to implement that interface the reference counting will have any effect.
As others already said: Reference counting in interfaces will result in the class instance to be freed immediately when the reference count reaches 0. It is an implicit call to the Free method at that point in code. This will fail e.g. if two objects reference each other. True garbage collection will free the objects not when they go out of scope but when memory is needed, so there is no performance impact every time the reference count reaches 0 because the object will just continue to exist. In addition a good garbage collector will detect the isolated circular references (e.g. A references B references C references A but nothing else references any of these objects) and will free these objects as well.
Garbage collection is different from simple ref counting. You can have automatic deletion when a ref count reaches 0, but that too is not garbage collection. Garbage collection means letting go of your ability to control when things are deleted from memory, and allowing the underlying language's implementation to optimize the behviours. You stop paying attention to reference counts, and trust in the dynamic behaviours of a particular implementation of garbage collection.
Naturally, garbage collection uses a system of reference counting to know when something is no longer referenced, but that is a small piece of the puzzle.
Reference counting is a form of garbage collection, but not a very good one. It is used by some languages (python I think) although often with cycle detection.
Even if you descended from TInterfaceObject, the object is not reference counted and thus garbage collected unless you only use the interface reference and not the object reference.
I.e. you would need to use
Var
nameable: IMyInterface;
begin
nameable:= IMyInterface.Create();
nameable.x(y);
etc
end;
This implies that your interface needs to support already the methods and properies that you require which quickly becomes tedious as you need to create an interface for each class.
It can be done reasonably easily in D2009 or later though. See Barry Kelly's implimentation of smart pointers. The usual reference countng cavets apply though.

Resources