Deleting TList within a TList - delphi

I am trying to free Tlist within a Tlist in a onDestroy event and FastMM4 is raising an access violation error. Here is the code snippet.
procedure TSignalFrm.FormDestroy(Sender: TObject);
var
x,y: integer;
begin
for x := 0 to signalList.Count - 1 do
begin
for y:=0 to TSignal(SignalList.Items[x]).alarmList.Count-1 do
begin
TAlarm(TSignal(SignalList.Items[x]).alarmList.Items[y]).Free;
end;
TSignal(SignalList.Items[x]).AlarmList.Free;
TSignal(SignalList.Items[x]).Free;
end;
SignalList.Free;
end;
I get access violation error at TSignal(SignalList.items[x]).Free; line. Freeing AlarmList items before freeing SignalList items raises the access violation error, but WHY?
Update: I am using Delphi 7.0 on Windows XP. The actual FastMM4 messages is as follows.
FastMM has detected an attempt to call a virtual method on a freed object. An access viloation will now be raised in order to abort the current operation.
Freed Object class: TList
Virtual method: Destroy
Virtual method address:427CF0
The allocation number was: 80055
Followed by a lots of memory dump.
According to this FastMM4 error, if you free an object within an another object, you automatically free the owner as well. I know that can't be true, but correct me if I am wrong.

Does TSignal not free its AlarmList member in its destructor? (That’s how I would do this).
Update: does it work if you remove the TSignal(SignalList.Items[x]).AlarmList.Free; line?
Second update:
Each TList's items need to be freed, if it contains pointers to objects.
Your problem was that TSignal is not a TList. Since it takes care of freeing its members (such as the Alarmlist), that Alarmlist should not be freed explicitly.

Since TAlam and TSignal are both objects (not records) I believe you should use TObjectList instead of TList. TObjectList has a special property calld OwnsObjects that allows it to free it's contents properly as it is being freed. Check this out http://docwiki.embarcadero.com/VCL/XE/en/Contnrs.TObjectList.OwnsObjects
As an advice do not use TList unless you need to store pointers not objects.

Related

Does this FreeAndNil(lAux) frees my double field too?

I'm correcting some (a lot) memory leaks of a project. I have some Delphi experience but is not my main language so I'm extra careful at freeing stuff.
I've already tried it and everything looks fine, but I thought that it would free the Field too (not what I want). Does that happen just with Objects?
TMainObject = class(TObject)
public
FDoubleField : double;
*
*
*
procedure TMainObject.CalculateSomeFieldValue();
var
lAux : TAuxObject;
begin
lAux := TAuxObject.Create;
lAux.RecoverData;
if **some condition** then
begin
FDoubleField := lAux.DoubleProperty;
end
else
begin
FDoubleField := lAux.OtherDoubleProperty;
end;
FreeAndNil(lAux);
end
Thanks in advance
Edit: I do not want to lose FDoubleField because I will use it later, but I need to free lAux.
The FDoubleField field doesn't need to be freed because it will be automatically "freed" as soon it goes out of scope.
Some tips:
You don't need to use FreeAndNil(lAux) in this case, just use lAux.Free because there's no need to set a pointer to nil which will no longer be used.
At the beginning, you can set ReportMemoryLeaksOnShutDown := True (documentation). In this way, you will be notified about any memory leak when the application closes.
Use try-finally blocks for being sure to always free the object you created
Modified code using try-finally block and Free:
procedure TMainObject.CalculateSomeFieldValue();
var
lAux : TAuxObject;
begin
lAux := TAuxObject.Create;
try
lAux.RecoverData;
if **some condition** then
begin
FDoubleField := lAux.DoubleProperty;
end
else
begin
FDoubleField := lAux.OtherDoubleProperty;
end;
finally
lAux.Free;
end;
end
In the example you give, you don't need to free anything for a variable of type double in a class (Also called a "field").
Field that must be freed are classes or simple pointers of any type that have been allocated.
The normal place to free data in a class is in the destructor.
Also pay attention to interfaces. They are generally reference counted and as such MUST NOT be freed. Frequently, interfaces are assigned a value by calling a class constructor and you must really look if the value returned by the class constructor is assigned to a variable of an interface type or to a variable of some object type. Assuming TAuxObject also implement the interface IAuxInterface, your have the following valid code:
var
AuxObj : TAuxObject;
AuxIntf : IAuxInterface;
begin
AuxIntf := TAuxObject.Create; // This one must NOT be freed
AuxObj := TAuxObject.Create; // This one must be freed
try
....
finally
AuxObj.FRee;
end;
end;
Properly using interfaces is a big subject. There are cases where interfaces are not reference counted.
There are in Delphi libraries a few classes designed to be ancestor for object supporting interface (For example TInterfacedObject). This ancestor implement reference counting properly (Methods QueryInterface, _AddRef and _Release). If your object do no derive from a class already implementing reference counting, then if you need reference counting then you must implement methods QueryInterface, _AddRef and _Release. As soon as they are defined, some compiler magic will call them when it is needed. And by the way freeing the object must actually done by the _Release method implementation.
Things becomes even more complex if the developer make use of weak and unsafe keywords to mark the interface type variable.

Is there a way to instantiate a desired number of objects in Delphi, without iterating?

I think that C++ supports something on the lines of :
Object objects[100];
This would instantiate a 100 objects, right? Is it possible to do this in Delphi (specifically 2007)? Something other than:
for i:=0 to 99 do
currentObject = TObject.Create;
or using the Allocate function, with a passed size value a hundred times the TObject size, because that just allocates memory, it doesn't actually divide the memory and 'give' it to the objects.
If my assumption that the c++ instantiation is instant rather than under-the-hood-iterative, I apologize.
What you are looking for is impossible because
Delphi does not support static (stack allocated) objects.
Delphi objects do not have default constructors that can be automatically invoked by compiler.
So that is not a lack of 'sugar syntax'.
For the sake of complete disclosure:
Delphi also supports legacy 'old object model' (Turbo Pascal object model) which allows statically allocated objects;
Dynamic object allocation itself does not prevent automatic object instantiation syntax, but makes such a syntax undesirable;
Automatic object instantiation syntax is impossible because Delphi does not have default constructors: Delphi compiler never instantiate objects implicitly because it does not know what constructor to call.
While you can't do what you want using objects, if your objects are relatively simple, you may be able to get what you want by using an array of records.
Records in Delphi can have properties (including setters and getters), and class and instance methods. They are created automatically when declared, so declaring an array of them will create them all without iterating.
For more info: http://docwiki.embarcadero.com/RADStudio/XE3/en/Structured_Types#Records_.28advanced.29.
(I'm not sure when the new functionality was added to Delphi, it may well be after the 2007 version).
I don't know of any non-hacky way to do this besides iterating:
var
MyObjects: array[0..99] of TMyObject;
i: Integer;
begin
for i := 0 to 99 do
MyObjects[i] := TMyObject.Create;
end;
That declaration wouldn't create 100 objects, it would just give you an array of 100 object references that point to nothing useful.
Creating an object is a two step process. The first step is allocating memory (which your code also doesn't), the second step is calling the constructor (Create method) to initialize that memory, create additional objects, etc, etc.
The allocation part can be done without the loop, but the constructor needs to be called to intialize each instance.
Many VCL classes don't have an additional constructor. They just have the empty constructor that does nothing. In that case, there is no need to call it.
For instance, to fetch an array of stringlists, you can use the following code, adjusted from this example:
type
TStringListArray = array of TStringList;v
var
Instances: array of Byte;
function GetStringLists(Number: Integer): TStringListArray;
var
i: Integer;
begin
// Allocate instance memory for all of them
SetLength(Instances, Number * TStringList.InstanceSize);
// Zero the memory.
FillChar(Instances[0], Length(Instances), 0);
// Allocate array for object references.
SetLength(Result, Number);
for i := 0 to High(Result) do
begin
// Store object reference.
Result[i] := #Instances[i * TStringList.InstanceSize];
// Set the right class.
PPointer(Result[i])^ := TStringList;
// Call the constructor.
Result[i].Create;
end;
end;
And to get an array of 100 stringlists:
var
x: TStringListArray;
begin
x := GetStringLists(100);
So while this procedure may save you a neglectable amount of time, and may theoretically be more memory-efficient (less fragmentation), you will still need the loop. No easy way out.
It is somewhat possible in Delphi (but is not very practical in a Delphi environment, unless you are writing a custom memory manager). Creating an object instance is a two-step process - allocating memory for the object, and constructing the object's members inside of that memory. There is nothing requiring the memory of a given object to be allocated individually. You can allocate a larger block of memory and construct multiple objects inside of that block, taking advantage of a feature of Delphi that calls a constructor like a normal method if it is called from an instance variable instead of a class type, eg:
var
objects: array of Byte;
obj: TSomeClass;
begin
SetLength(objects, 100 * TSomeClass.InstanceSize);
FillChar(objects[0], 0, Length(objects));
for i := 0 to 99 do
begin
obj := TSomeClass.InitInstance(#objects[i * TSomeClass.InstanceSize]));
obj.Create;
end;
...
for i := 0 to 99 do
begin
obj := TSomeClass(#objects[i * TSomeClass.InstanceSize]);
obj.CleanupInstance;
end;
SetLength(objects, 0);
end;
This is not much different than what C++ does behind the scenes when declaring an array of object instances, only C++ supports declaring the array statically and it will call the constructors and destructors automatically, whereas Delphi does not support that.
There are a number of third-party implementations that allow you to allocate objects on the stack or in user-defined buffers, such as:
Objects on the Stack: A Delphi Relic
Allocate objects on stack, at specified memory address, or through any memory manager
Just to name a couple.

Why does freeing a bad object pointer throw EPrivilege instead of EAccessViolation?

Why do i get an "EPrivilege - Privileged instruction" when I execute this procedure instead of Access Violation?
{$Warnings OFF}
procedure TFrmMyTest.mnuCrashMeClick(Sender: TObject);
var t: TStringList;
begin
FreeAndNil(t);
end;
{$Warnings ON}
I know that I try to free an object that points randomly in memory. But I expect to get an access violation and not "Privileged instruction".
(Don't worry I don't intend to use the code above in a real program.)
FreeAndNil calls the non virtual method Free. Which first checks for nil(the variable likely isn't nil) and then calls the virtual destructor Destroy.
Calling a virtual method means looking at the beginning of an object to get the virtual-method-table(VMT). This can throw an access violation. But if the object is in allocated memory, it will instead return an undefined pointer as VMT.
Next a pointer sized value is read at a certain offset from the VMT. This once again can throw an access violation or return an undefined pointer.
Finally the memory where this pointer points is executed. And if it happen to contain invalid code, you get some variant of an invalid instruction exception.
Sometimes you will get an access violation and sometimes you will get EPrivilege and no doubt there are other modes of failure. And even sometimes the code will appear to work and the crash will happen later. It all depends on what value happens to be in t when you call Free on it.

How to free an arraylist of objects in a Delphi Prism?

I need to free list of objects stored in an ArrayList. I know you can call Free procedure in Delphi, but in Delphi Prism there is no free procedure. I don't just want to remove objects from the list but also free it from its memory.
For instance Say I have this following class
TheClass = Class
private
theStr:String;
protected
public
end;
method TheForm;
begin
TheArrayList:=new ArrayList;
end;
To Add Object I would do this:
method TheForm.AddToList;
var
tmpObj:TheClass;
begin
tmpObj := new TheClass;
TheArrayList.Add(tmpObj);
end;
To Delete Object from the list, this is how I would do it but there is no free
procedure.
method TheForm.DeleteFromList;
var I:integer;
begin
for I:=0 to theArrayList.count-1 do
begin
theClass(theArrayList[I]).free; <-------I know this doesnt work.
theArrayList.RemoveAt(I);
end;
end;
end;
How is freeing list of object accomplished in Delphi Prism?
Thanks,
Since your class is not holding onto any unmanaged resources like files, window handles, database connections etc. you need do nothing beyond letting the .net garbage collector free the memory when it decides the time is right.
Trying to force the garbage collector to run ahead of time typically leads to worse performance than simply letting it do its job.
If you had a class with unmanaged resources then you should follow the IDisposable pattern.
while theArrayList.count > 0 do
theArrayList.RemoveAt(0);
GC will help you.
Delphi Prism programs run on .NET. There is no need to free any objects, since the garbage colleector will eventually do that. As someone already commented, you can call IDisposable.Dispose() to free other resources than memory, if the object implements it.
There is also the using construct, which is a bit like Create-try-finally-Free-end in Delphi:
using MyArrayList = new ArrayList do
begin
// use ArrayList...
end; // IDisposable(ArrayList).Dispose is called, if applicable.
This won't work for the items in the array, of course. If you really want, you can call Dispose on each of them. But generally, this is not necessary.
So:
method TheForm.DeleteFromList;
begin
theArrayList.Clear;
end;
No need to free anything.

Reference-counting for objects

In my code I use a small data-storing class, which is created in different places. To avoid memory leaks and simplify things, I want to use reference counting, so I did
type TFileInfo = class (TInterfacedObject, IInterface)
and removed all my manual calls to TFileInfo.Free. Unfortunately Delphi reported a lot of memory leaks. Searching on SO I found the following question explaining why this doesn't work:
Why aren't descendants of TInterfacedObject garbage collected?
There is a workaround presented there but it requires me (at least if i get it right) to write a custom interface IFileInfo and provide it with a lot of getters and setters, which I want to avoid.
EDIT I should add that I insert the create FileInfo objects into two different kinds of hash tables: one descending from TBucketList and another one is a hash map implementation from the Codegear forum. Internally they both user pointers, so the situation is just like in the other question.
Is there any other possibility to make objects in Delphi use reference-counting?
The reference counting in Delphi only works if you only have a reference to your instance via an interface. As soon as you mix interface references and class references then you are in trouble.
Essentially you want reference counting without the need to create an interface with all the methods and properties defined in it. There are three ways to do this, and these are roughly in the order I would recommend them.
Barry Kelly wrote a post about Smart Pointers. It uses the Generics in Delphi 2009, but I am pretty sure you could hard code it to the specific versions of type you are using if you are not using 2009 yet (it is a great release BTW).
Another way that works with more versions of Delphi and less modification is the value type wrapper by Janez Atmapuri Makovsek. It is an example implemented for TStringList, but you could adapt it for any type.
The third way is to create a interfaced pointer (similar to Barry's Smart Pointer, but not so smart). I believe there is one in JCL, but I don't remember the details for sure. Basically this is an interface that accepts a TObject reference at construction. Then when it's reference count reaches zero it calls free on the object you passed to it. This method really only works for short lived instances that you are no passing as parameters because you separate the reference counted reference from the actually used reference. I would recommend one of the other two methods instead, but if you prefer this method and want more information just let me know.
That is the thing about Delphi, there are a free ways of accomplishing things. Option #1 is the best one in my opinion - Get Delphi 2009 and use that method if you can.
Good luck!
Unfortunately, the Delphi compiler generates the necessary code to inc/dec reference count only when you use interfaces (in your case custom interface IFileInfo). Moreover, if interfaces are cast to pointer (or TObject for that matter), again no reference counting is possible. For example, assumming global variable list : TList:
var ifi : IFileInfo;
begin
ifi := TFileInfo.Create;
list.Add(TFileInfo(ifi));
end;
after the method returns list[list.Count - 1] will contain dangling pointer.
So interfaces cannot be used in a hashmap that casts them to pointers, the hashmap implementation must keep them as IInterface.
Don't mix object references and interface references.
var
Intf: IInterface;
Obj: TFileInfo;
begin
// Interface Reference
Intf := TFileInfo.Create; // Intf is freed by reference counting,
// because it's an interface reference
// Object Reference
Obj := TFileInfo.Create;
Obj.Free; // Free is necessary
// Dangerous: Mixing
Obj := TFileInfo.Create;
Intf := Obj; // Intf takes over ownership and destroys Obj when nil!
Intf := nil; // reference is destroyed here, and Obj now points to garbage
Obj.Free; // this will crash (AV) as Obj is not nil, but the underlying object
// is already destroyed
end;
This functionality is supplied for interfaces but not for objects.
You can create something like it, but you need to override some of the structure of TObject:
TRefCountObject = class (TObject)
private
FRefCount : Integer;
public
constructor Create;
procedure Free; reintroduce;
function RefCountedCopy: TRefCountObject;
end;
constructor TRefCountObject.Create;
begin
inherited;
FRefCount := 1;
end;
procedure TRefCountObject.Free;
begin
if self=nil then Exit;
Dec(FRefCount);
if FRefCount<=0 then
Destroy;
end;
function TRefCountObject.RefCountedCopy: TRefCountObject;
begin
Inc(FRefCount);
Result := self;
end;
You need RefCountedCopy to assign the object to another variable. But then you have a refcounted object.
How to use this:
var1 := TRefCountObject.Create; // rc = 1
var2 := var1.RefCountedCopy; // rc = 2
var3 := var1.RefCountedCopy; // rc = 3
var2.Free; // rc = 2
var1.Free; // rc = 1
var4 := var3.RefCountedCopy; // rc = 2
var3.Free; // rc = 1
var4.Free; // rc = 0
If you want to eliminate calls to free on TObject instances then you might want to look at a garbage collector for native Delphi. I am aware of 2 different garbage collectors and a garbage collecting technique, each with pros and cons.
Native Precise Tracking Garbage Collector by Henrick Hellström
API for Boehm Garbage Collector DLL by Barry Kelly
Garbage Collector for Delphi Objects and Components by Rossen Assenov (not a real garbage collector, more of a memory bag.)
One of those will probably work for you.
To add to what has already been said, if you want to store references to Interfaces, instead of using a TList, use a TInterfaceList. The ref count will work consistently.
There's a long explanation to this, but in short: Inheriting from TInterfacedObject (and not calling Free yourself), is not enough, you need to use an object-factory-dynamic to create the objects for you, and use interface-pointers to the object everywhere, not just object-reference-variables. (Yes, that means you can't just switch 'old code' without looking it over)

Resources