wowwwwwwww theo....... your explaination was greate Thanks for nice explaination. Iqbal
--- In [email protected], Theodoros Bebekis <[EMAIL PROTECTED]> wrote: > > 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 > ------------------------ >

