Access violation on release of TObjectList

I have the following Delphi code:

destructor TXX_XXXX.Destroy; var i: Integer; begin if Assigned(Allocations) then begin for i:=0 to (Allocations.Count - 1) do begin try TXX_ALOC(Allocations.Items[i]).Free; except on Ex:Exception do begin OutputDebugString(PChar('Exception Error Message '+ Ex.Message)); end; end; end; // Above code works well - no exception try FreeAndNil(Allocations); {Exception Here} except on E:Exception do begin OutputDebugString(PChar('Exception in xxxxxxxxx.pas'+E.Message)); end; end; end; inherited; end; 

Access violation at address 4003AB4 in module Vcl50.bpl. Reading Address 2980BFFC

I know that access violation is usually caused by

  • release some object that was released before
  • use some object without initialization

But here, before I do the free, I checked that Allocations is assigned. If I refuse to handle exceptions, my application will throw something wrong. Allocations is a TObjectList, if it is an array - I doubt that I have assigned a length to the array, but it is a TObjectList.

Thanks a lot!

+4
source share
3 answers

A TObjectList usually takes care to destroy its contents. Do not free your objects in this case. This will result in access violation when releasing the TObjectList , as it again tries to free the contained objects.

This behavior of the list of objects can be controlled in its constructor:

 constructor TObjectList.Create(AOwnsObjects: Boolean); 

Use this to indicate whether you want the list to own its content (meaning: it takes care to destroy the item when it is removed from the list or the list is destroyed) or not. A constructor without a parameter (which you probably used) sets it to true .

You probably just need a list of type TList , but for storing objects. If this is the case, then create your list as follows:

 Allocations:= TObjectList.Create(False); 

But if you want auto kill behavior, then just remove the for-loop. The list of objects will destroy your TXX_ALOC objects.

+18
source

As a rule, when clearing lists, you want to execute a cycle from the end to the beginning, i.e.

 for i := (Allocations.Count - 1) downto 0 do begin Delete(Allocations.Items[i]); end 

but in the case of TObjectList , if the list owns the objects (which it does by default), you should not free them until the container is destroyed, because the list will do it for you. In the above code, if the list belongs to objects, then calling Delete also frees the object.

+7
source

There are 2 options for your ...

1) Create a TObjectList if aOwnsObjects is set to true, if you want Delphi to automatically release objects when they are deleted from the ObjectList. And in your Destructor, just the FreeAndNil is the ObjectList itself. Then you remove all the objects from the list and release them automatically. Since freeing an ObjectList will automatically free the objects contained in this list, your code might look like this:

 destructor TXX_XXXX.Destroy; begin FreeAndNil( Allocations ); // inherited; end; 

2) Create a TObjectList if aOwnsObjects is set to False, in which case you will need to free the objects in the list yourself. Then your code might look something like this:

 destructor TXX_XXXX.Destroy; var i : Integer; oObject : TObject; begin if Assigned(Allocations) then begin for i:= Pred( Allocations.Count ) downto 0 do begin // Get a reference to the Object oObject := TXX_ALOC(Allocations.Items[i]); // Remove the object from the object list Allocations.Delete( i ); // Free the Object FreeAndNil( oObject ); end; end; FreeAndNil( Allocations ); inherited; end; 
+3
source

All Articles