O/H Andries Bos έγραψε:
> 
> 
> 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


Andries

Objects are pointers.
(we just don't need to use the de-referencing operator ^
  with them).

Pointers point to a memory block or nowhere (=nil).
So, objects point to a memory block or nowhere (=nil).

The memory block (read object), sometimes called memory object,
exists in memory. Just once.

You may have a variable pointing to that
memory block (read object).

var
   B : TButton;
begin
   B := TButton.Create(nil);

   // more code here
end;

You may have _more_than_a_single variable
pointing to that very same memory block;

var
   A, B: TButton;
begin
   A := TButton.Create(nil);
   B := A;

   // more code here
end;

When the above is true, and it happens very frequently,
then the programmer has to be extremely carefull
and, somehow, nilify ALL those variables
when that memory block, they all point to, is freed (destroyed).
Otherwise, a trouble is near.

var
   A, B: TButton;
begin
   A := TButton.Create(nil);
   B := A;

   B.Free;
   A.Click; // oups
end;

The GENERAL roule is: code that allocates a memory block
is responsible for that memory block de-allocation.
That is: a function/procedure/method that creates an object
is responsible for freeing it.

Regarding parameters that are objects,
(parameters are variables local to a function)
here is an example which applies that rule.

procedure ListService(List: TStrings);
begin
   // 1. assume the List is created
   // 2. do something with the List
   // 3. do NOT destroy the List
end;

var
   List : TStringList;
begin
   List := TStringList.Create;
   try
     ListService(List);
   finally
     List.Free;
   end;
end;

Here is a very common situation.

procedure ClearList(List: TStrings);
var
   i : integer;
begin
   for i := 0 to List.Count - 1 do
     if List.Objects[i] <> nil then
       List.Objects[i].Free;
   List.Clear;
end;


Of course there are exceptions to that
memory block responsibility rule.
But, as always, we should have a very good reason
for breaking a rule.

One, the most frequent, exception says:
"the callee creates the object
  but the caller is responsible for freeing it"

An example that breaks
the memory block responsibility rule.

function  Split(S: string; Delim: Char): TStrings; // caller must dispose Result
beging
   Result := TStringList.Create;
   // split S based on Delim
   // and Add() to Result
end;


var
   S : string;
   List : TStrings;
begin
   S := 'Provider=OLEDB4;Data source=C:\Data.MDB';

   List := Split(S, ';');
   try
     //do something with the List
   finally
     List.Free;
   end;
end;

Regarding functions that return an object
that must be freed by the caller,
here is a very common situation.

function Select(const SQL: string): TDataset;
begin
   Result := TSomeQueryClass.Create(nil);
   // setup Result, giving it a TConnection etc
   Result.SQL.Text := SQL;
   Result.Active := True;
end;


An object parameter may also be passed by reference,
that is as var or out (online help denotes the difference).
By reference means that "I pass _the_address_of_ my variable
and, please, make my variable point to where it should point".

procedure GetList(var List: TStrings);
begin
   if IsMonday then
     List := MondayComboBox.Items
   else
     List := SaturdayComboBox.Items;
end;

(
   ...the above as function

function GetList: TStrings;
begin
   if IsMonday then
     Result := MondayComboBox.Items
   else
     Result := SaturdayComboBox.Items;
end;

and a function that utilizes an _untyped_ out parameter
to return an object

function  Find(List: TComponentList; const Name: string; out Obj): Boolean;
var
   i : Integer;
begin
   Result := False;
   for i := 0 to List.Count - 1 do
     if AnsiSameText(Name, List[i].Name) then
     begin
       TComponent(Obj) := List[i];
       Result := True;
       Exit;
     end;
end;

)


Well, who is responsible for freeing that
resulting List or object? (lol).

Well, it depends on the situation, as always.
And its a good habit to document all those,
and similar functions,
providing instructions to its user.




-- 
Regards
Theo

------------------------
Theo Bebekis
Thessaloniki, Greece
------------------------
Greek_Delphi_Prog : a Delphi Programming mailing list in Greek at
    http://groups.yahoo.com/group/Greek_Delphi_Prog

CSharpDotNetGreek : A C# and .Net mailing list in Greek language at
    http://groups.yahoo.com/group/CSharpDotNetGreek

atla_custom : a Unisoft Atlantis Customization mailing list at
    http://groups.yahoo.com/group/atla_custom
------------------------

------------------------------------

-----------------------------------------------------
Home page: http://groups.yahoo.com/group/delphi-en/
To unsubscribe: [EMAIL PROTECTED] Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/delphi-en/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/delphi-en/join
    (Yahoo! ID required)

<*> To change settings via email:
    mailto:[EMAIL PROTECTED] 
    mailto:[EMAIL PROTECTED]

<*> To unsubscribe from this group, send an email to:
    [EMAIL PROTECTED]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/

Reply via email to