Link to home
Start Free TrialLog in
Avatar of mimran
mimran

asked on

Resource Leak on Form create

Hi, I am using BoundsChecker to detect leaks using Delphi 5.  When I call a modal form, it reports resource leak on inherited Create (owner) line, even though I have tried to call create with different ways, and I even removed the constructor method, and instead put the code in form.Create, but it is still reporting leak.  Amazingly, boundschecker does not report leak in some other modal forms with create or without create constructor.  I must have to remove this leakage.  I am not creating any object like TStringList in constructor.  I will really appreciate your help.  The sample code is as below in which leak reported:

procedure TfrmAR.BitBtn2Click(Sender: TObject);
var
   f: TfsARMST;
   CustNo,CustName: String;
begin
   inherited;
   try
     f := TfsARMST.Create(Self, CustNo, CustName); //<--BoundsChecker shows leak here if no constructor defined.
     if f.Showmodal = mrOK then
          Edit1.Text := CustNo;
   finally
     f.Free;
   end;
end;

//-----------
unit sARMST
. . .
 private
    { Private declarations }
    ReturnValue1 : ^string;
    ReturnValue2: ^String;
    procedure CreateQuery;
  public
    constructor Create(AOwner:TComponent; var Value1:string; Var Value2: String);
  end;

constructor TfsARMST.Create(AOwner:TComponent; var Value1:string; Var Value2:string);
begin
 inherited Create(AOwner);  //<<----BoundsChecker shows leak here if constructor defined.

 Query1.Databasename:= FSDataModule.FSDMDb.DatabaseName;
 ReturnValue1 := @Value1;
 ReturnValue2 := @Value2;
 ComboBox1.ItemIndex := 0;
 EFind.Text := Value1;
 CreateQuery;
end;

procedure TfsARMST.CreateQuery;
Var
   ACN: String;
begin
  with Query1 do
  begin
    Close;
    SQL.Clear;
    SQL.Add('Select AR_KY_MST_ACN, ');
    SQL.Add('      AR_FD_MST_NAME, ');
    SQL.Add('      AR_FD_MST_TEL_NO, ');
    SQL.Add('      AR_KY_MST_SNM, ');
    SQL.Add('      AR_FD_MST_CITY,');
    SQL.Add('      AR_FD_MST_STATE ');
    SQL.Add('FROM AR_DS_MST_R ');
   
    if  ComboBox1.ItemIndex=1 then
    begin
        SQL.Add('WHERE AR_KY_MST_ACN Like :ACN' );
        ParamByName('ACN').AsString := EFind.Text+'%';
        if RGSortOrder.ItemIndex=0 then
            SQL.Add(' ORDER BY AR_KY_MST_ACN ASC')
        else
            SQL.Add(' ORDER BY AR_KY_MST_ACN DESC');
    end;
 end;
end;

Thanks

Avatar of PGKalle
PGKalle

I can only describe a related problem appearing in Delphi 5: Within a ShowModal-constructed Form you sometimes have (very strange and from system to system different (!!)) compiler errors. Perhaps it is a compiler bug still not fixed.

What I did (after a long period of discussions with friends and some computer sciences students): I did not directly call commands concerning objects which are subclasses of the new created one (= the ShowModal Form) in the Creator- as well as in the OnCreate-procedures.
The alternative: all initializing commands concerning objects of your ShowModal-Form are e.g. called the first time when called OnPaint of your Form, afterwards the command execution is blocked by a global (boolean) flag. Then you have the check if the boolean flag is still active every time you repaint your Form, but that should be a no problem viewed from the perspective of calculation time complexity.

Perhaps you try this (very unusual, I agree) possibility. If it works without any mistakes then, we could consider contacting Borland for a bugfix. If you really have the same problems I had with my last project, that surely is a compiler bug.

Kalle
Avatar of mimran

ASKER

Hi Kalle,

Thanks for yr suggestion.  Before testing yr suggetion, I did one thing.  I am neither creating any contructor method nor initializing anything in form.onCreate event.  So I am just creating and opening like a simple form like:

try
   f := TfsARMST.Create(Self);
   f.showmodal;
finally
   f.Free;
end;

Boundschecker is reporting resource leak on Create (Self).  I don't know what's happening, but I will test your suggesting and let's see..:)

Hm,

funny thing. ;-)
Is your Form declared to be not auto-generated [=static] by program startup? Normally this simple thing you did now should work...
Or what if you use "Application" instead of "Self" as the owner?

Kalle
The memory leak is from the string handling code.

 ReturnValue1 := @Value1;
 ReturnValue2 := @Value2;

It is odd, but Delphi copies Value1 and Value2, then assigns the addresses of the copies to the ReturnValue variables.

I learned of this recently from another question on EE, and it immediately predicted/explained a number of memory leak situations to me.

Also, in this case, the strings being passed are owned by an unknown scope.  So far as the "Create" method is converned, the strings may be deallocated at any time by the proper scope owner.

Rather than making the ReturnValue's ^String, I would recommend just making them String so that their scope is known (the current object) and Delphi's transparent memory management for strings can function without side effects.

This is the price paid for the nearly automatic string handling that we take for granted today.  We really need to pay atention to the details of the memory management scheme or we get bit.
Avatar of mimran

ASKER

Auto generate (Autocreate) form is unchecked.
I want to draw yr main attention the same problem with its parent form.  Actually, the following line creates a dialog box as a 'lookup' to select a value from, and pastes the value on actual or parent form.

f := TfsARMST.Create(Self, CustNo, CustName);

I can fix this leak by replacing with my own created 'lookup' which is not leaking any resources, but there is resource leak in parent form on create method which I am more concerned of.  

procedure TfFMAR37.BitBtn2Click(Sender: TObject);  //Calling parent form from menu
var
   f: TfFMAR37A;  //Parent form
begin
   inherited;
   try
     f := TfFMAR37A.Create(Self);  //<-- BoundsChecker shows leak here if I remove constructor method from parent form.
     f.Showmodal;
   finally
     f.Free;
   end;
end;

//-- Parent form constructor method...
constructor TfFMAR37A.Create(AOwner: TComponent);
var
   Size: Cardinal;
   User: array[0..20] of Char;
   c4 : integer ;
begin
   inherited Create(AOwner);  //<-- BoundsChecker shows leak here if delphi calls parent's constructor method.

   with StringGrid1 do
   begin
      Cells[0, 0] := 'Ref. #';       Cells[2, 0] := 'Amt Left';
      Cells[1, 0] := 'Org Amt';      Cells[3, 0] := 'Date';
   end;

   with StringGrid2 do
   begin
      Cells[0, 0] := 'Ship To';
      Cells[1, 0]  := 'Inv. #';         Cells[2, 0] := 'Inv. Date';
      Cells[3, 0] := 'Desc';           Cells[4, 0] := 'Amount';
   end;

// Get User ID
   Size := 20;
   GetUserName(User, Size);
   Label9.Caption := Uppercase(Copy(User, 1, 20));
end;

This is how other forms are created, but boundschecker is showing resource leak in some forms, not all of them.  BoundsChecker is also showing lots of leak in Controls.pas library at SetProp function.  I don't know what the heck it is and how to fix.  

I don't if this is a bug, but the application sometimes crash with 'system out of resources'.  

Thanks for your any advice in advance.
It sounds like it is time to upgrade to D7.
Bad thing. Wonder what "out of recources" means...

Perhaps the algorithm really addresses another dynamically (not already existing) form as the owner and there is an internal invalid pointer operation (expected goal but found "nil" or so on).

The only thing I can suggest: Test it with different owners of the new created Form (e.g. "Application" or even a new custom (dummy) parent). So you should eliminate all eventualities concerning bad parent references.

If that doesn't work, I say it's one of Borlands problems. As said, I also had many problems with dynamically generated Forms - perhaps that is a product area not so much used and thus not well enough financed in development.

Kalle
Our Of Resources could mean kernel handles, memory, file handles, or any other resource.  You need to get more detailed information.

I have had no problems with dynamically creating forms, apart from the initial conceptual gap.  In reality, all forms are created dynamically.  You can even visit the code in your application.
Avatar of mimran

ASKER

I appreciate yr time spent to answer.

hmm..It sounds like problem is in Delphi.  

How can I create my own dynamic parent instead of 'self' for creating form?  I tried with 'Application' before, but did not work.  Memproof is showing unfreed resources by Kernel32.dll, MFC42.dll, and in unit sysinit.pas and system.pas.

Can you help me solve:
* BoundsChecker is showing 16 byte memory leak in Sysinit.pas delphi library in "InitThreadTLS" procedure at p := LocalAlloc(LMEM_ZEROINIT, Longint(@TlsLast));

* In Registry.pas, Stack memory overrun error, copying 4 bytes to Info.RegData starting offset.....(need to increase stack size or something?)

* Many Resource leaks in controls.pas library allocated by SetpropA function.  I don't know how to fix this leaks.

Thanks. I appreciate your reply.
you can use NIL for the owner, but then you need to manage freeing the form yourself on application close.

Stack over run error is usually due to recursion.  You probably have an event loop or tail recusrion error

resource leaks in controls.pas - sounds like it is time to upgrade to D7 or D8.
And Delphi 6 was well known as a buggy release - I never used it because we went straight to 6.
ASKER CERTIFIED SOLUTION
Avatar of swift99
swift99

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mimran

ASKER

hi everyone, thanks for your comments.

Now, I compiled the application in Delphi 7, In order to test in debugging tool, I have memory Sleuth 3 downloaded trial version, I think it supports delphi 7 but I don't have unlock key!  Turbopower is not in the bussiness anymore, so would anyone like to share the key with me, if it is not legal to do so??

Thanks.
Avatar of mimran

ASKER

you all gave me valuable suggestions, I appreciate you all.  
I think, finally all I have to check leak in delphi 7, so I need memory sleuth 3 unlock key.
I am wondering, if anyone can share the key...
Thanks you all again..
Avatar of mimran

ASKER

It seems like it is delphi 5 library leaking.  So far I have fixed few leaks inside my application, not delphi lib.  
I accept swift99 answer.
Thanks everyone.
question from mimran:  what version of boundschecker are you using?  I used to work with Boundschecker back when I Was still programming in delphi 3.  It worked great and I was very happy with it.  But now I'm using delphi 5 and I can't get Boundschecker to integrate with delphi.

So any info you could provide about what version of boundschecker does work with delphi 5 would be very helpful to me.

Thanks in advance.