Dowemo


Question:

I want to know the best way to free a TList filled with record.

I have the following record:

type


TPkBill = record


    PkBill: integer;


    Constructor Create(c_PkBill: integer);



constructor TPkBill.Create(c_PkBill: integer);


begin


    PkBill := c_PkBill;


end;


I create the list and fill it with the record:

procedure TfrmProject.lvBillDblClick(Sender: TObject);


var   


   i, iCount: integer;


   item: TListItem;


   oPkBill: TPkBill;


   lstPkBill: Tlist;


begin


   iCount := 0;


   lstPkBill:= TList.Create;



   //if an item is selected in lv


   if (lvBill.ItemIndex = -1) then begin exit; end


   else


   begin


        //Loop through all items and get selected item


        for i := 0 to lvBill.Items.Count - 1 do


        begin


            item := lvBill.Items.Item[i];


            if(item.Selected = true)then


            begin


                //create new item


                oPkBill := TPkBill.Create(StrToInt(lvBill.Items[i].Caption));


                //add it to a list


                lstPkBill.Add(TObject(oPkBill)); 


                //add up


                iCount := iCount +1;      


            end;


        end;


        //Now we have a list ok pkBill



        if(iCount > 1)then //other stuff I do


    end


I want to be able to free the TList and also to free the record.

Here is what I already tried:

for i := 0 to lstPkBill.Count - 1 do


begin


    //TObject(TPkBill(lstPkBill[i])).Free;  //Acces violation at adress..


    //FreeMem(TPkBill(lstPkBill[i]));   //Incompatible types


    //FreeMem(TObject(lstPkBill[i]));   //Incompatible types


end;


lstPkBill.Clear;


FreeAndNil(lstPkBill);


Thanks you for the help, it's appreciated!


Best Answer:


You have defined a record with a constructor. Calling a record constructor does not allocate memory on the heap, like a class constructor does. Your oPkBill variable exists on the stack. Calling oPkBill := TPkBill.Create(...) merely populates the members of that variable. You are then type-casting that entire variable (which only contains one Integer member) into a TObject pointer. You are not actually allocating any memory on the heap for the list item, so there is no need to free them.

I suspect what you were actually trying to do is something more like this:

type


  PPkBill = ^TPkBill;


  TPkBill = record


    PkBill: integer;


    Constructor Create(c_PkBill: integer);


  end;



constructor TPkBill.Create(c_PkBill: integer);


begin


  PkBill := c_PkBill;


end;



procedure TfrmProject.lvBillDblClick(Sender: TObject);


var   


  i: Integer;


  item: TListItem;


  oPkBill: PPkBill;


  lstPkBill: TList;


begin


  if lvBill.ItemIndex = -1 then Exit;



  //an item is selected in lv



  lstPkBill := TList.Create;


  try


    //Loop through all items and get selected items


    for i := 0 to lvBill.Items.Count - 1 do


    begin


      item := lvBill.Items.Item[i];


      if item.Selected then


      begin


        //create new item


        New(oPkBill);


        try


          oPkBill^ := TPkBill.Create(StrToInt(lvBill.Items[i].Caption));


          //add it to a list


          lstPkBill.Add(oPkBill);


        except


          Dispose(oPkBill);


          raise;


        end;


      end;


    end;



    //Now we have a list ok pkBill


    if (lstPkBill.Count > 1) then


    begin


      //other stuff I do


    end;


  finally


    for i := 0 to lstPkBill.Count - 1 do


      Dispose(PPkBill(lstPkBill[i]));


    lstPkBill.Free;


  end;


end;





Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs