Solved

problem with the stringlist

Posted on 2009-05-12
8
333 Views
Last Modified: 2012-05-06
I created a procedure that query database to obtain the records.
I moved a qry to the class which returns StringList to the main form.
I am getting an error with the Eureka Log - multifree error leak.
Thus, makes me wonder maybe my code is incorrect when comes to freeing objects.
 


procedure TfrmDataViewerGUI.tcTest(const sqlStat: string);

var

  recordNum , i : integer;

  lsStations : TStringList;

  qStations : TDBOperator;

  n,k, gridCol, gridRow : integer;

begin

  lsStations := TStringList.Create;

  try

    qStations := TDBOperator.create(sqlStat,connectionString);

    try

      recordNum := qStations.recordCount;

      if recordNum <> 0 then

      begin

        lsStations := qStations.qryStations;

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

        begin

          ShowMessage('station ' + lsStations[i]);

        end;

         qStations.closeConn;

      end

      else

      begin

        ShowMessage('no records');

      end;

    finally
 

      qStations.Free;

    end;

  finally

    lsStations.Free;

  end;
 

  ShowMessage('num of records  ' + IntToStr(recordNum));
 

end;

//----------------------------------------------------

unit uDB;
 

interface

uses

   Windows,Classes,StdCtrls,StrUtils,SysUtils, Messages,Dialogs

   ,ADODB;

 Type

    TDBOperator = Class(TObject)

    private

      FadoConn : TADOConnection;

      Fsql, FConnStr : string;

      FStationID : integer;

      FRecordCount : integer;

      FCountsList : TStringList;

      FstationList : TstringList;
 
 
 

    public

      constructor create (const ASql, AConnStr : string); overload ;

      constructor create (const Asql, AConnStr : string; const countID : integer);overload;

      function queryResultTCLowerGrid : TStringList;

      function qryStations : TStringList;

      function recordCount : integer;

      procedure closeConn;
 

end;
 

implementation
 

{ TDBOperator }
 

constructor TDBOperator.create(const ASql, AConnStr: string);

begin

  Fsql := Asql;

  FConnStr := AConnStr;

  FstationList := TStringList.Create;

end;
 

procedure TDBOperator.closeConn;

begin

  FstationList.Free;

end;
 

constructor TDBOperator.create(const Asql, AConnStr: string;

  const countID: integer);

begin
 

end;
 

// verify if there are any records per query

function TDBOperator.recordCount: integer;

var

  qry : TADOQuery;

  recNum : integer;

begin

  qry := TADOQuery.Create(nil);

  try

    qry.ConnectionString := FConnStr;

    qry.Close;

    qry.SQL.Clear;

    qry.SQL.Add(Fsql);

    qry.Open;

    //----------------------------------

    try

      qry.Active := true;

           except on e: EADOError do

           begin

                MessageDlg('Error while doing query', mtError,

                      [mbOK], 0);
 

              Exit;

          end;

       end; //end try adoQry.Active

    recNum := qry.RecordCount;

  finally

  FreeAndNil(qry);

  end;
 

  Result := recNum;

end;
 

// return qry results to the form

function TDBOperator.qryStations: TStringList;

var

  qry : TADOQuery;

  recNum : integer;

  i: integer;

begin

  qry := TADOQuery.Create(nil);

  try

    qry.ConnectionString := FConnStr;

    qry.Close;

    qry.SQL.Clear;

    qry.SQL.Add(Fsql);

    qry.Open;

    //----------------------------------

    try

      qry.Active := true;

           except on e: EADOError do

           begin

                MessageDlg('Error while doing query', mtError,

                      [mbOK], 0);
 

              Exit;

          end;

       end; //end try adoQry.Active
 

     recNum := qry.RecordCount;

     for i := 0 to recNum - 1 do

     begin

      FstationList.Add(qry.Fields.Fields[0].asstring);

      FstationList.Add(qry.Fields.Fields[1].asstring);

     end;
 

  finally

    qry.Free;

  end;
 

  result := FstationList;
 

end;
 

function TDBOperator.queryResultTCLowerGrid: TStringList;

begin
 

end;
 
 
 

end.

Open in new window

0
Comment
Question by:mordauth
  • 4
  • 3
8 Comments
 
LVL 14

Accepted Solution

by:
SteveBay earned 500 total points
Comment Utility
change
   lsStations := qStations.qryStations;
to
   lsStations.Assign(qStations.qryStations);
0
 
LVL 12

Expert Comment

by:Hypo
Comment Utility
I think I could point out a few things that you could aprove i your code, but anyway, the answer to your question about what causes the "multifree error leak" is because the function qryStations returns a TStringList that is owned by the TDBOperator class, and will be freed TDBOperator class, but it is also handed over to the Form that also free it. I see what you are trying to do with lsStations, but you should understand that when you assign an object with another object, then you don't copy the data of the objects, but instead you just replace the object pointers.

Change your code acordingly, and it will probably work.

regards
Hypo
procedure TfrmDataViewerGUI.tcTest(const sqlStat: string);

var

  recordNum , i : integer;

  lsStations : TStringList;

  qStations : TDBOperator;

  n,k, gridCol, gridRow : integer;

begin

  lsStations := TStringList.Create;

  try

    qStations := TDBOperator.create(sqlStat,connectionString);

    try

      recordNum := qStations.recordCount;

      if recordNum <> 0 then

      begin

        lsStations.Assign(qStations.qryStations);

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

        begin

          ShowMessage('station ' + lsStations[i]);

        end;

         qStations.closeConn;

      end

      else

      begin

        ShowMessage('no records');

      end;

    finally
 

      qStations.Free;

    end;

  finally

    lsStations.Free;

  end;
 

  ShowMessage('num of records  ' + IntToStr(recordNum));

end;

Open in new window

0
 
LVL 12

Expert Comment

by:Hypo
Comment Utility
too slow again... :)
0
 
LVL 14

Expert Comment

by:SteveBay
Comment Utility
Answer quick, offer explainations later:)
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 12

Expert Comment

by:Hypo
Comment Utility
Yep... but also my explaination was a bit flawed :(
This line: "but you should understand that when you assign an object with another object, then you don't copy the data of the objects, but instead you just replace the object pointers." can be missinterpreted as if I meant that the Assign() method replaces the poitners, but what I meant was of course that the assign operator := replaces the pointers. Sometimes I wish they would reinstate the edit function. :)
0
 
LVL 1

Author Comment

by:mordauth
Comment Utility
Thanks for the asnwers,
Are you ok if I split the points ?
350 to Steve
150 to Hypo
0
 
LVL 12

Expert Comment

by:Hypo
Comment Utility
You don't need to split the points for my sake, Steve answered your question first, and it was a correct answer. :)
0
 
LVL 14

Expert Comment

by:SteveBay
Comment Utility
I agree that the assignment of Object pointers is one of the easiest ways to create hard to find bugs in Delhi applications. However, it can be a very powerful technique when used correctly.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now