Hi Andries,
The AV you experienced in ProcedureOne is actually caused by your
assignment of lStringlist in procedureTwo. I've renamed the variables
in your sample code for clarity because your use of LStringlist in both
ProcedureOne and procedureTwo will cause some confusion in my
explanation:
procedure ProcedureOne;
var
LStringlist1 : TStringlist;
begin
LStringlist1 := TStringlist.create;
LStringlist1.add....
ProcedureTwo(LStringlist1);
if LStringlist1 <> nil then
LStringlist1.free;
end;
procedure ProcedureTwo(AStringList : TStringlist = nil);
var
LStringlist2 : TStringlist;
begin
if AStringlist = nil then
LStringlist2 := TStringlist.create
else
LStringlist2 = AStringlist;
//do something
LStringlist2.free;
end;
procedure ProcedureThree
begin
ProcedureTwo;
end;
The variables LStringlist1, LStringlist2 and AStringlist are simply
pointers to chunks of memory that represent your objects. Delphi knows
how to reference these chunks of memory because of the class definition
of TStringList.
So, when you create LStringlist1 in ProcedureOne and pass it to
ProcedureTwo, all you're really doing is passing the memory address of
LStringlist1. In ProcedureTwo, you assign this memory address to a new
local variable, LStringlist2 - which means that now both LStringlist1
and LStringlist2 point to exactly the same place in memory(!). So, when
you free LStringlist2, you are in effect, also freeing LStringlist1.
This is why you get an AV when you try to free LStringList1 (again) in
ProcedureOne. As far as Delphi is concerned, the object pointed to by
LStringlist1 no longer exists.
As for your code above, was it your intention to assign the contents of
LStringlist1 to LStringlist2 so that you could do something to
LStringlist2 without changing LStringlist1? If so, then you probably
wanted to do something like this:
procedure ProcedureTwo(AStringList: TStringList = nil);
var
LStringList2: TStringList;
begin
LStringList2 := TStringList.Create;
if Assigned(AStringList) then
LStringList2.Assign(AStringList);
//do something
LStringList2.Free;
end;
Every programmer that you speak to will have their own preference as to
where and when you should be freeing your objects. As my own rule of
thumb, I like my methods to maintain ownership of the objects that they
create. This helps to keep my code more readable and maintainable, and
doesn't lead to unexpected AVs when some method somewhere else in my
code frees an object that I'm still expecting to use elsewhere.
I hope this helps.
Cord
From: [email protected] [mailto:[EMAIL PROTECTED] On
Behalf Of Andries Bos andriesbos-at-yahoo.com |Delphi-En|
Sent: 04 June 2008 11:28
To: Cord Schneider
Subject: [delphi-en] explaination on assings and free parameters
Hello
What are the do and donn't when passing Lists from one procedure to
another.
I do have three different procedures:
ProcedureOne;
var
LStringlist : TStringlist;
begin
LStringlist : TStringlist.create;
LStringlist.add....
procedureTwo(Lstringlist);
if LStringlist <> nil then
LStringlist.free;
end;
procedureTwo(AStringList : TStringlist = nil);
var
lStringlist : TStringlist;
begin
if AStringlist = nil then
lStringlist := TStringlist.create
else
lStringlist = AStringlist;
//do something
LStringlist.free;
end;
ProcedureThree
begin
proceduretwo;
end
I had an AV problem when freeeing the LStringlist in procedureOne. This
was because it's already been freed in ProcedureTwo.
However where and when should the lStringlist in each procedure be
freed?
( I thought that after lStringlist = AStringlist in procedureTwo and the
LStringlist.free the original LStringlist in ProcedureOne would also
have been freed; Debugging shows that this is not true. )
I hope your answers would help me understand how and when a parameter
may and should be freed.
Regards
Andries
[Non-text portions of this message have been removed]