Solved

Resource Leak on Form create

Posted on 2003-10-27
16
577 Views
Last Modified: 2010-04-05
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

0
Comment
Question by:mimran
  • 6
  • 6
  • 3
  • +1
16 Comments
 

Expert Comment

by:PGKalle
Comment Utility
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
0
 

Author Comment

by:mimran
Comment Utility
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..:)

0
 

Expert Comment

by:PGKalle
Comment Utility
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
0
 
LVL 6

Expert Comment

by:swift99
Comment Utility
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.
0
 

Author Comment

by:mimran
Comment Utility
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.
0
 
LVL 6

Expert Comment

by:swift99
Comment Utility
It sounds like it is time to upgrade to D7.
0
 

Expert Comment

by:PGKalle
Comment Utility
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
0
 
LVL 6

Expert Comment

by:swift99
Comment Utility
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.
0
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

 

Author Comment

by:mimran
Comment Utility
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.
0
 
LVL 6

Expert Comment

by:swift99
Comment Utility
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.
0
 
LVL 6

Expert Comment

by:swift99
Comment Utility
And Delphi 6 was well known as a buggy release - I never used it because we went straight to 6.
0
 
LVL 6

Accepted Solution

by:
swift99 earned 250 total points
Comment Utility
Delphi 5 was a buggy release (aargh!  not enough caffeinne!  Caffeinne!)
0
 

Author Comment

by:mimran
Comment Utility
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.
0
 

Author Comment

by:mimran
Comment Utility
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..
0
 

Author Comment

by:mimran
Comment Utility
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.
0
 

Expert Comment

by:DirkVerdonck
Comment Utility
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.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

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…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 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

13 Experts available now in Live!

Get 1:1 Help Now