reynaerde
asked on
Memory leak - how to get rid of custom created object
Well, this has already cost me too many hours so I decided to sign up with experts-exchange, I hope you can help me here.
I'm not really a programming crack, so I just might be doing something really stupid but here is what I tried to do:
The object is part of a larger program, it is defined in one unit(say unit A) as follows:
TLattice = class(TObject)
cell : array of array of TCell;
size_dim1, size_dim2, lifetime : Integer;
cellCountH, cellCountA1, cellCountA2, cellCountA3, cellCountD : array of integer;
active_drugs : integer;
drugs_in_system : array of TDrug;
constructor create(Dimensie1, Dimensie2 : Integer);
end;
TCell and TDrug are defined as follows:
TCell = class(TObject)
status : cell_status;
nA1, nA2 : integer;
strand: integer;
to_update : cell_status;
lifetime: integer;
resist: integer;
activated: bool;
constructor create();
end;
TDrug = class(TObject)
name: string;
N: integer;
Presp : double;
lifetime: integer;
constructor create();
end;
And, to be as complete as possible, the constructor for TLattice is this:
constructor TLattice.create(Dimensie1, Dimensie2 : Integer);
var
Temp_Cell : TCell;
Teller1, Teller2 : Integer;
begin
setlength(cell,Dimensie1+( 2*bufferzo ne),Dimens ie2+(2*buf ferzone)); // set dynamic array => dimensions + bufferzone
self.size_dim1 := Dimensie1;
self.size_dim2 := Dimensie2;
setlength(cellCountH,1000) ;
setlength(cellCountA1,1000 );
setlength(cellCountA2,1000 );
setlength(cellCountA3,1000 );
setlength(cellCountD,1000) ;
for Teller1 := 0 to Dimensie1 + (2*bufferzone -1) do
begin
for Teller2 := 0 to Dimensie2 + (2*bufferzone -1) do // vul lattice 2e dimensie
begin
Temp_Cell := TCell.create();
self.cell[Teller1,Teller2] := Temp_Cell;
end;
end;
end;
Now, in one unit(unit A) I have registered a variable called Lattice as a global variable(in that unit)
var
Lattice : TLattice;
From another unit(unit B) I call a wrapper procedure which is as follows:
procedure wrapper(some variables..)
begin
Lattice := TLattice.create(700,700);
Do some things with the Lattice..
Then, in the end, I try to get rid of this object since I call this wrapper procedure many times and it causes gigantic memory leaks
First I simply tried Lattice.free(); but this doesn't seem to work(I get a memory access error)
(I don't access the Lattice anymore after this call)
Next I tried to make a custom procedure(freeLattice) to clean it up and though it partly works(much less memory leak) it still doesn't totally solve
my problem
end;
procedure freeLattice(Lattice : TLattice);
var
Teller, Teller1, Teller2, Dimensie1, Dimensie2: Integer;
begin
Dimensie1 := Lattice.size_dim1;
Dimensie2 := Lattice.size_dim2;
for Teller1 := bufferzone to Dimensie1 + (bufferzone -1) do
begin for Teller2 := bufferzone to Dimensie2 + (bufferzone -1) do
begin
Lattice.cell[Teller1,Telle r2].Free() ;
end;
end;
setlength(Lattice.cell,0,0 );
setlength(Lattice.cellCoun tH,0);
setlength(Lattice.cellCoun tA1,0);
setlength(Lattice.cellCoun tA2,0);
setlength(Lattice.cellCoun tA3,0);
setlength(Lattice.cellCoun tD,0);
setlength(Lattice.drugs_in _system,0) ;
end;
I hope someone can shed some light on this! :)
I'm not really a programming crack, so I just might be doing something really stupid but here is what I tried to do:
The object is part of a larger program, it is defined in one unit(say unit A) as follows:
TLattice = class(TObject)
cell : array of array of TCell;
size_dim1, size_dim2, lifetime : Integer;
cellCountH, cellCountA1, cellCountA2, cellCountA3, cellCountD : array of integer;
active_drugs : integer;
drugs_in_system : array of TDrug;
constructor create(Dimensie1, Dimensie2 : Integer);
end;
TCell and TDrug are defined as follows:
TCell = class(TObject)
status : cell_status;
nA1, nA2 : integer;
strand: integer;
to_update : cell_status;
lifetime: integer;
resist: integer;
activated: bool;
constructor create();
end;
TDrug = class(TObject)
name: string;
N: integer;
Presp : double;
lifetime: integer;
constructor create();
end;
And, to be as complete as possible, the constructor for TLattice is this:
constructor TLattice.create(Dimensie1,
var
Temp_Cell : TCell;
Teller1, Teller2 : Integer;
begin
setlength(cell,Dimensie1+(
self.size_dim1 := Dimensie1;
self.size_dim2 := Dimensie2;
setlength(cellCountH,1000)
setlength(cellCountA1,1000
setlength(cellCountA2,1000
setlength(cellCountA3,1000
setlength(cellCountD,1000)
for Teller1 := 0 to Dimensie1 + (2*bufferzone -1) do
begin
for Teller2 := 0 to Dimensie2 + (2*bufferzone -1) do // vul lattice 2e dimensie
begin
Temp_Cell := TCell.create();
self.cell[Teller1,Teller2]
end;
end;
end;
Now, in one unit(unit A) I have registered a variable called Lattice as a global variable(in that unit)
var
Lattice : TLattice;
From another unit(unit B) I call a wrapper procedure which is as follows:
procedure wrapper(some variables..)
begin
Lattice := TLattice.create(700,700);
Do some things with the Lattice..
Then, in the end, I try to get rid of this object since I call this wrapper procedure many times and it causes gigantic memory leaks
First I simply tried Lattice.free(); but this doesn't seem to work(I get a memory access error)
(I don't access the Lattice anymore after this call)
Next I tried to make a custom procedure(freeLattice) to clean it up and though it partly works(much less memory leak) it still doesn't totally solve
my problem
end;
procedure freeLattice(Lattice : TLattice);
var
Teller, Teller1, Teller2, Dimensie1, Dimensie2: Integer;
begin
Dimensie1 := Lattice.size_dim1;
Dimensie2 := Lattice.size_dim2;
for Teller1 := bufferzone to Dimensie1 + (bufferzone -1) do
begin for Teller2 := bufferzone to Dimensie2 + (bufferzone -1) do
begin
Lattice.cell[Teller1,Telle
end;
end;
setlength(Lattice.cell,0,0
setlength(Lattice.cellCoun
setlength(Lattice.cellCoun
setlength(Lattice.cellCoun
setlength(Lattice.cellCoun
setlength(Lattice.cellCoun
setlength(Lattice.drugs_in
end;
I hope someone can shed some light on this! :)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Well, unfortunately this doesn't change anything (other than perhaps a few bits less, the Drugs_in_system array is not used in my program yet)
Also, I find it strange that I get an error when I insert Lattice.free();
The exact error reads:
project raised exception class EAccessViolation with message 'Access violation at address blabla in module project_name. Read of address blabla
Also, I find it strange that I get an error when I insert Lattice.free();
The exact error reads:
project raised exception class EAccessViolation with message 'Access violation at address blabla in module project_name. Read of address blabla
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
From the DELPHI 7 help:
To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
ASKER
Actually, I just got it from the Delphi help(using Delphi 7)
'To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.'
I know the 2-dimensional array consists of arrays within arrays, but that suits my purpose fine.
Thanks for the comments about the low(), high() and length() methods though.
'To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.'
I know the 2-dimensional array consists of arrays within arrays, but that suits my purpose fine.
Thanks for the comments about the low(), high() and length() methods though.
It might be a problem with the USAGE of lattice. I tried all the code that's been posted and don't get any errors. Not even a memory leak. I do not have the create/destroy methods for tcell though.
It's possible something your doing with lattice is overwriting memory or some other problem.
It's possible something your doing with lattice is overwriting memory or some other problem.
Just to clarify...I'm using your lattice.create, my lattice.destroy and doing this:
procedure TForm2.Button2Click(Sender : TObject);
begin
Lattice := TLattice.create(700,700);
lattice.free;
end;
With no error.
If you post more code (tcell.create) and some usage, someone may be able to shed some light on it.
procedure TForm2.Button2Click(Sender
begin
Lattice := TLattice.create(700,700);
lattice.free;
end;
With no error.
If you post more code (tcell.create) and some usage, someone may be able to shed some light on it.
ASKER
Ah, yes! You are entirely right. As unfortunately happens so often I overlooked something quite important.
I was under the impression I was clearing the Lattice using
for Teller1 := bufferzone to Dimensie1 + (bufferzone -1) do
begin
for Teller2 := bufferzone to Dimensie2 + (bufferzone -1) do
begin
Lattice.cell[Teller1,Telle r2].Free() ;
end;
end;
But clearly I needed to get the whole array (0 to Size_Dim2 + (2*bufferzone -1))
Thanks a bunch for helping!
(and thanks to alex for giving me some pointers for using high, low etc)
I was under the impression I was clearing the Lattice using
for Teller1 := bufferzone to Dimensie1 + (bufferzone -1) do
begin
for Teller2 := bufferzone to Dimensie2 + (bufferzone -1) do
begin
Lattice.cell[Teller1,Telle
end;
end;
But clearly I needed to get the whole array (0 to Size_Dim2 + (2*bufferzone -1))
Thanks a bunch for helping!
(and thanks to alex for giving me some pointers for using high, low etc)
You probably need to release the drugs array, too...
TLattice=class
destructor Destroy;
override;
end;
Destructor TLattice.Destroy;
create(Dimensie1, Dimensie2 : Integer);
var
Teller1, Teller2 : Integer;
begin
for Teller1 := 0 to Size_Dim1 + (2*bufferzone -1) do
begin
for Teller2 := 0 to Size_Dim2 + (2*bufferzone -1) do
begin
self.cell[Teller1,Teller2]
end;
end;
//Free Drugs_In_System array here...
for x:=? to ? do
Drugs_in_System[x].free;
inherited destroy;
end;