Theodorus, your explanation was great .... It's now clear to me who's responsible for what....
thanks ----- Original Message ---- From: Theodoros Bebekis <[EMAIL PROTECTED]> To: [email protected] Sent: Wednesday, June 4, 2008 2:48:51 PM Subject: Re: [delphi-en] explaination on assings and free parameters 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 [Non-text portions of this message have been removed] ------------------------------------ ----------------------------------------------------- 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/

