Link to home
Start Free TrialLog in
Avatar of reynaerde
reynaerde

asked on

destructor - override: memory management(again)

So, this is basically a follow up to another question I posted earlier about memory management.

Consider the following classes:

TCell = class(TObject)
  status : cell_status;
  nA1, nA2 : integer;
  strand: integer;
  to_update : cell_status;
  lifetime: integer;
  resist: integer;
  activated: bool;
  constructor create();
end;

TMargolusBlock = class(TObject)
  cell : array[0..3] of TCell;
  cellCountH, cellCountA1, cellCountA2, cellCountA3, cellCountD : integer;
  LatticeReference1, LatticeReference2 : Integer;
  constructor create(cell0,cell1,cell2,cell3 : TCell);
  //destructor Destroy;
   // override;
end;

TMargolusArray = class(TObject)
  mblock : array of array of TMargolusBlock;
  constructor create(size : Integer);
  destructor Destroy;
    override;
end;

These are the constructors:

constructor TMargolusBlock.create(cell0,cell1,cell2,cell3 : TCell);
begin
  self.cell[0] := cell0;
  self.cell[1] := cell1;
  self.cell[2] := cell2;
  self.cell[3] := cell3;
  self.cellCountH := 0;
  self.cellCountA1 := 0;
  self.cellCountA2 := 0;
  self.cellCountA3 := 0;
  self.cellCountD := 0;
end;

constructor TMargolusArray.create(size : Integer);
begin
  setlength(mblock, size+1, size+1);
end;


Now, I tried using a custom destructor:

When I only use the second one it works(I think, I have some suspicions about memory usage/leakage)
but when I add the first one (Destructor TMargolusblock.Destroy) I get an error
Can anyone explain this to me?

{*
Destructor TMargolusblock.Destroy;
var
  Teller1 : Integer;
begin
    for Teller1 := 0 to 3 do
    begin
      cell[Teller1].Free();
    end;
   inherited destroy;
end;
*}

Destructor TMargolusArray.Destroy;
var
  Teller1, Teller2 : Integer;
begin
    for Teller1 := low(mblock[0]) to high(mblock[0]) do
    begin
      for Teller2 := low(mblock[0]) to high(mblock[0]) do
      begin
        mblock[Teller1, Teller2].Free();
      end;
    end;
   inherited destroy;
end;

This is when using another procedure to fill the MargolusArray.

After some debugging/testing I also noticed that this gives an error(related I guess):

constructor TMargolusArray.create(size : Integer);
var
  Teller1, Teller2 : Integer;
  empty_cell : TCell;
  empty_margolus : TMargolusBlock;
begin
  setlength(mblock, size+1, size+1);

  empty_cell := TCell.create;
  empty_margolus := TMargolusBlock.create(empty_cell,empty_cell,empty_cell,empty_cell);
  for Teller1 := 0 to size do
  begin
    for Teller2 := 0 to size do
    begin
      mblock[Teller1, Teller2] := empty_margolus;
    end;
  end;

Or even:
  mblock[5,5] := empty_margolus;
  mblock[5,6] := empty_margolus;

end;

I thought the mblock[index1,index2] was just a pointer to the empty_margolus memory location..?

Hope someone can explain it to me :)
Avatar of geobul
geobul

Hi,

When you are defining a constructor you have to call 'inherited Create' as a first command in the constructor:

constructor TMargolusArray.create(size : Integer);
begin
  inherited Create;
  setlength(mblock, size+1, size+1);
end;

Regards, Geo
SOLUTION
Avatar of Wim ten Brink
Wim ten Brink
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@geobul, nope... Wrong :-P

If the base class is TObject then technically the only thing the inherited constructor does is zero the instance memory before it's used. Still, it is a very good idea to call the inherited Create method since it initializes data that you might need. It's just a bit sloppy if you don't...
I'd use:

Destructor TMargolusblock.Destroy;
var
  Teller1 : Integer;
begin
    for Teller1 := 3 downto 0 do
    begin
      cell[Teller1].Free();
    end;
   inherited destroy;
end;

Regards, Geo
I had in mind:

Destructor TMargolusblock.Destroy;
var
  Teller1 : Integer;
begin
    for Teller1 := 3 downto 0 do
    begin
      cell[Teller1] := nil; // not Free
    end;
   inherited destroy;
end;

Sorry.
Avatar of reynaerde

ASKER

Ok, but:

- I thought free() checks for nil reference anyway
- Why can't I assign two variables pointing at the same object?

constructor TMargolusArray.create(size : Integer);
var
  empty_cell : TCell;
  empty_margolus : TMargolusBlock;
begin
  setlength(mblock, size+1, size+1);

  empty_margolus := TMargolusBlock.create(TCell.create,TCell.create,TCell.create,TCell.create);

  mblock[5,5] := empty_margolus;
  mblock[5,6] := empty_margolus;

end;

This code gives me an error, WITHOUT using any destructor..
I'm sorry, I stand corrected on the last point, there was another error in my code causing the error.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That is more or less what I'm trying to do, only the problem is:

* I need to be able to have different cells in the MargolusBlock point to the same cell AND free the memory afterwards..
For example, in my program I will have:

(not real code, just to give an idea)
MA1, MA2 : TMargolusArray;
cellA : TCell;

where:

cellA := TCell.create();
MA1 := TMargolusArray.create(10);
MA2 := TMargolusArray.create(10);

MA1.mblock[1, 2] := TMargolusBlock.create(cellA,cellX1,cellX2,cellX3);
MA2.mblock[2, 2] := TMargolusBlock.create(cellA,cellY1,cellY2,cellY3);

Using this constructor:

constructor TMargolusBlock.create(cell0,cell1,cell2,cell3 : TCell);
begin
  self.cell[0] := cell0;
  self.cell[1] := cell1;
  self.cell[2] := cell2;
  self.cell[3] := cell3;
  self.cellCountH := 0;
  self.cellCountA1 := 0;
  self.cellCountA2 := 0;
  self.cellCountA3 := 0;
  self.cellCountD := 0;
end;

So, instead of creating a new TCell, I'm just referencing an already existing TCell.

The assignment part works fine, only when it comes to freeing it afterwards I run into problems..
Is there any way to have this working? Or should I really make a copy of each TCell?? This would mean a LOT of extra work since I'm accessing the TCells through a number of different Objects(not just TMargolusArrays, but also TLattice, another class which has an array of cells in it)

Thanks a bunch in advance!




SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well, I finally managed to bring my memory leak down from something like 20MB/100 iterations to around 10 bytes. Still not perfect but good enough for me. I still don't feel I really understand the different aspects of memory management but certainly feel I have a better grasp.
So, thank you both a lot. I hope you feel the division of points is a fair one.
Thanks again!