Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2004-06

Memory leak in freepascal, FreeAndNil not working properly?

7 messages · 5 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andreas Gros

Hi folks,

please check out this code (unit). Certainly there is something very strange going on in handling memory in freepascal. I'm using Free Pascal Compiler version 1.9.4 [2004/05/30] for i386.

Thanks in advance for replying.

Andreas

{ snip%<************************************************************************ Pascal unit: testObject
Author: Andreas Gros <andreas.gros at biozentrum dot uni-wuerzburg dot de> }

unit testObject;
interface
uses
  SysUtils, Types, Classes, Variants;
procedure test();
type 	TTestObj = class(TObject)
				public
				Findex : Integer;
				constructor Create(_index : Integer);
			end;
implementation
constructor TTestObj.Create(_index : Integer);
	begin
	Findex := _index;
	end;
procedure test();
	var list : TList;
			i : Integer;
			t : TTestObj;
	begin
	list := TList.Create();
	//create 6 TTestObj-ects with ascending indices
	for i := 0 to 5 do
		begin
		list.add(TTestObj.Create(i));
		end;
	t := TTestObj(list.first());
	//writes 0 to stdout
	writeln(t.Findex);
	FreeAndNil(t);
	list.pack();
	t := TTestObj(list.first());
	{the next line should write 1 to stdout, because the first object was freed,
	 but the result is 0!!!
	 it is still the old index, the object is still existing and FreeAndNil as
	well as TList.pack have no effect}
	writeln(t.Findex);
	{ but now the crux: you can't say free again:
	   an access violation error message turns up}
	FreeAndNil(t);
	end;
end.

{ snip%<************************************************************************} testobj.pp:
{ snip%<************************************************************************} program main;
uses testObject in 'testObject.pas';

begin
 test();
end.
{ snip%<************************************************************************}
Andreas Gros Forschungsstation Fabrikschleichach Uni Wuerzburg Glashuettenstr. 5 96181 Rauhenebrach

Reply by email

Peter Vreman
to Andreas Gros
Show quoted text 7 lines
Hi folks, please check out this code (unit). Certainly there is something very strange going on in handling memory in freepascal. I'm using Free Pascal Compiler version 1.9.4 [2004/05/30] for i386.

<snip code>

You code is wrong, it also crashes with kylix.

Reply by email

Michael Van Canneyt
to Andreas Gros: please check out this code (unit). Certainly there is something very strange going on in…
Andreas Gros wrote 59 lines
Hi folks, please check out this code (unit). Certainly there is something very strange going on in handling memory in freepascal. I'm using Free Pascal Compiler version 1.9.4 [2004/05/30] for i386. Thanks in advance for replying. Andreas { snip%<************************************************************************ Pascal unit: testObject Author: Andreas Gros <andreas.gros at biozentrum dot uni-wuerzburg dot de> } unit testObject; interface uses SysUtils, Types, Classes, Variants; procedure test(); type TTestObj = class(TObject) public Findex : Integer; constructor Create(_index : Integer); end; implementation constructor TTestObj.Create(_index : Integer); begin Findex := _index; end; procedure test(); var list : TList; i : Integer; t : TTestObj; begin list := TList.Create(); //create 6 TTestObj-ects with ascending indices for i := 0 to 5 do begin list.add(TTestObj.Create(i)); end; t := TTestObj(list.first()); //writes 0 to stdout writeln(t.Findex); FreeAndNil(t); list.pack(); t := TTestObj(list.first()); {the next line should write 1 to stdout, because the first object was freed, but the result is 0!!! it is still the old index, the object is still existing and FreeAndNil as well as TList.pack have no effect}

Your logic is wrong.
FreeAndNil(T) did NOT remove the pointer from the list, the list has a COPY of the pointer . Hence List[0] is still different from Nil after the freeandnil, so Pack() will not remove it. The memory pointed to by the (invalid) pointer is not yet trashed, so the output is by chance 0.

You must do
  List.Remove(t);
  FreeAndNil(T);
the List.pack() is no longer necessary then.

Michael.

Reply by email

Andreas Gros
to Peter Vreman: <snip code> You code is wrong, it also crashes with kylix.
You code is wrong, it also crashes with kylix.

What kind of answer is this? That it is not working in Kylix either does certainly not mean their memory handling is correct.

Please look at the code. The crash is supposed to happen, because it is the same object, that is addressed both times I say FreeAndNil. But that means, that FreeAndNil is not working properly and due to that TList.pack can't work because it is not a nil-pointer, that's coming back from FreeAndNil.
Otherwise it can't be possible, to address the same object again after calling FreeAndNil.

Ciao

Andreas

Peter Vreman wrote 16 lines
> Hi folks, > > please check out this code (unit). Certainly there is something very > strange > going on in handling memory in freepascal. I'm using Free Pascal Compiler > version 1.9.4 [2004/05/30] for i386. <snip code> You code is wrong, it also crashes with kylix. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Andreas Gros Forschungsstation Fabrikschleichach Uni Wuerzburg Glashuettenstr. 5 96181 Rauhenebrach

Reply by email

Peter Vreman
to Andreas Gros
> You code is wrong, it also crashes with kylix. What kind of answer is this? That it is not working in Kylix either does certainly not mean their memory handling is correct.

Kylix and Delphi are the references whether special constructions should work or not.

See Michael's answer what is wrong with your code.

Reply by email

Matt Emson
to Andreas Gros: What kind of answer is this? That it is not working in Kylix either does certainly not…
> You code is wrong, it also crashes with kylix. What kind of answer is this?

The correct one?

To remove an item from a TList you must:

(a) set it to nil and pack the list

e.g.

  list[0] := nil;
  list.pack;

(b) call TList.Delete(index)

e.g.

  list.delete(0);

(c) use TList.Remove(pointer)

e.g.

  list.remove(t);

Did the explanation not make sense? You obviusly do not understand how pointers wor... right? A pointer points to a memory address. Setting a pointer to nil, does not remove that block of memory from existance... for example:

var
  a, b: TObject;
begin
  a := TObject.Create;
  b := a; //b points at a
  freeandnil(a);
  //at this point, b still points to the memory allocated to a, but this
memory is no longer valid, and it will A/V if you free b
  b.free; //access violation...
end;

Do you understand now?

Matt

Reply by email

Anton Tichawa
to Matt Emson
Matt Emson wrote 58 lines
>>You code is wrong, it also crashes with kylix. >> >> >What kind of answer is this? > > The correct one? To remove an item from a TList you must: (a) set it to nil and pack the list e.g. list[0] := nil; list.pack; (b) call TList.Delete(index) e.g. list.delete(0); (c) use TList.Remove(pointer) e.g. list.remove(t); Did the explanation not make sense? You obviusly do not understand how pointers wor... right? A pointer points to a memory address. Setting a pointer to nil, does not remove that block of memory from existance... for example: var a, b: TObject; begin a := TObject.Create; b := a; //b points at a freeandnil(a); //at this point, b still points to the memory allocated to a, but this memory is no longer valid, and it will A/V if you free b b.free; //access violation... end; Do you understand now? Matt _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

that should read:

..
begin
  a := TObject.Create;  // a points to a newly created object
  b := a;  // b now points to the same object (that is already pointed
to by a)
..

anton.

Reply by email