Memory Leak

Discussion of open issues, suggestions and bugs regarding SDAC (SQL Server Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
mjrobles

Memory Leak

Post by mjrobles » Sat 04 Dec 2004 18:12

I'm using a trial version of SDAC so I want to buy SDAC components but I get a memory leak problem. I have a dll that uses a TMSConnection and TMSQuery and when a close my dll and release this 2 components I loss between 150 and 200 Kbytes of memory. This is a serious problem for me because I have a Middleware that never closes and this program loads and unloads dlls so if I loss 200 Kbytes everytime a dll unloads, for a month of executing the program, I will get about 300Mbytes of memory loss or more.

Thanks in advance

Ikar
Posts: 1693
Joined: Thu 28 Oct 2004 13:56

Re: Memory Leak

Post by Ikar » Mon 06 Dec 2004 09:06

We couldn't reproduce the problem.
Please send us complete small sample to demonstrate it.

Please supply us following information

- Exact version of Delphi or C++ Builder
- Exact version of SDAC. You can see it in About sheet of TMSConnection Editor

mjrobles

Memory Leak

Post by mjrobles » Tue 07 Dec 2004 14:43

It's a simple dll that creates TMSConnection and TMSQuery and before I call FreeLibrary I free these two components with the .Free instruction.

My delphi version is 5 with all service packs and fixes for it and the SDAC version is "SDAC version 3.00 for Delphi 5 [size 1464 Kb]" a trial version from this address "http://crlab.com/sdac/download.html"

mjrobles

I think I found the problem

Post by mjrobles » Wed 08 Dec 2004 17:08

I made 2 programs, one dll(MSDll) that creates and frees SDAC componentes and a .exe that loads and unloads this dll.

MSDll:
------------------
library MSDll;

uses
SysUtils,
Classes,
Windows,
MSAccess,
Dialogs,
ActiveX;

{$R *.RES}

var
Query : TMSQuery;
Conexion : TMSConnection;

function Entrada: Integer;
begin
try
CoInitialize(nil);
Query := TMSQuery.Create(nil);
Conexion := TMSConnection.Create(nil);

Conexion.ConnectString := 'Provider=SQLOLEDB.1;User ID=sa;Data Source=(local);Initial Catalog=TCADBPRU;Use Encryption for Data=0';
Conexion.LoginPrompt := False;
Conexion.Connected := True;
CoUninitialize;
except
on E: Exception do
showmessage(E.Message);
end;
Result := 0;
end;

function LiberaMemoria: Integer;
var
ren : String;
begin
try
CoInitialize(nil);
ren := '1';
Conexion.Connected := False;
ren := '2';
Conexion.Free;
ren := '3';
Query.Free;
ren := '4';
CoUninitialize;
ren := '5';
except
on E: Exception do
showmessage(E.Message+#13+'Ren: '+Ren);
end;
Result := 0;
end;

exports
Entrada,LiberaMemoria;
end.
------------------

MSDllLoader:

------------------

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1 : TForm1;
HandleDll : THandle;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
type
Entrada_ = function: Integer;
var
FEntrada : Entrada_;
REntrada : TFarProc;
begin
HandleDll := LoadLibrary(PChar('MSDll.dll'));
if HandleDll > 0 then
begin
REntrada := GetProcAddress(HandleDll,PChar('Entrada'));
FEntrada := Entrada_(REntrada);
FEntrada;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
LiberaMemoria_ = function: Integer;
var
FLiberaMemoria : LiberaMemoria_;
RLiberaMemoria : TFarProc;
begin
if HandleDll > 0 then
begin
RLiberaMemoria := GetProcAddress(HandleDll,PChar('LiberaMemoria'));
FLiberaMemoria := LiberaMemoria_(RLiberaMemoria);
FLiberaMemoria;
end;
end;

end.

-----------------

In the MSDllLoader you need to create a Form with 2 buttons: button1 and button2, activate OnClick Events so you can access the code above. The problem I found is when I Call "Conexion.Connected := False;" or "Conexion.Free;" in the "LiberaMemoria" function in MSDll, so the Connection component never frees. How can I do this to free this 2 components?

Marco J.
mrobles@tca.com.mx[/img][/code]

Ikar
Posts: 1693
Joined: Thu 28 Oct 2004 13:56

Re: Memory Leak

Post by Ikar » Thu 09 Dec 2004 09:58

You cannot call CoUninitialize before closing Conexion. Try to remove CoUninitialize from Entrada and CoInitialize from LiberaMemoria.

mjrobles

...

Post by mjrobles » Thu 09 Dec 2004 15:49

Ok then, i made what you told me to do and I'm not getting an error anymore but a memory leak persists. here is the complete source code and ckeck when FreeLibrary executes, I did load and unload the MSDll 5 times and this is my memory lost:
1st unload: 144 Kb
2nd unload: 172 Kb
3rd unload: 152 Kb
4th unload: 152 Kb
5th unload: 148 Kb

--------------------------------------------------------------------------------
SOURCE CODE
--------------------------------------------------------------------------------

MSDllLoader:
---------
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1 : TForm1;
HandleDll : THandle;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
type
Entrada_ = function: Integer;
var
FEntrada : Entrada_;
REntrada : TFarProc;
begin
HandleDll := LoadLibrary(PChar('MSDll.dll'));
if HandleDll > 0 then
begin
REntrada := GetProcAddress(HandleDll,PChar('Entrada'));
FEntrada := Entrada_(REntrada);
FEntrada;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
LiberaMemoria_ = function: Integer;
var
FLiberaMemoria : LiberaMemoria_;
RLiberaMemoria : TFarProc;
begin
if HandleDll > 0 then
begin
RLiberaMemoria := GetProcAddress(HandleDll,PChar('LiberaMemoria'));
FLiberaMemoria := LiberaMemoria_(RLiberaMemoria);
FLiberaMemoria;
FreeLibrary(HandleDll);
end;
end;

end.
--------


MDDll:
--------

library MSDll;

uses
SysUtils,
Classes,
Windows,
MSAccess,
Dialogs,
ActiveX;

{$R *.RES}

var
Query : TMSQuery;
Conexion : TMSConnection;

function Entrada: Integer;
begin
try
CoInitialize(nil);
Query := TMSQuery.Create(nil);
Conexion := TMSConnection.Create(nil);

Conexion.ConnectString := 'Provider=SQLOLEDB.1;User ID=sa;Data Source=(local);Initial Catalog=TCADBPRU;Use Encryption for Data=0';
Conexion.LoginPrompt := False;
Conexion.Connected := True;
except
on E: Exception do
showmessage(E.Message);
end;
Result := 0;
end;

function LiberaMemoria: Integer;
var
ren : String;
begin
try
ren := '1';
Conexion.Close;
ren := '2';
Conexion.Free;
ren := '3';
Query.Free;
ren := '4';
CoUninitialize;
ren := '5';
except
on E: Exception do
showmessage(E.Message+#13+'Ren: '+Ren);
end;
Result := 0;
end;

exports
Entrada,LiberaMemoria;
end.

-------

Hope you can help me, I buy your components already under mrobles@tca.com.mx user

Ikar
Posts: 1693
Joined: Thu 28 Oct 2004 13:56

Re: ...

Post by Ikar » Fri 10 Dec 2004 16:08

If to comment all references to SDAC in MSDll you can make sure that memory leaks persist. So the problem isn't in SDAC.

Most probably the problem is in added units Dialogs -> Controls -> Forms

mrobles@tca.com.mx

Problem solved

Post by mrobles@tca.com.mx » Mon 13 Dec 2004 16:16

No, this units are from delphi so I don't think so folk, there's a 4K memory leak when I unload the DLL but not 150K or more memory lost.

I Installed SDAC 3.00 already but NOT trial version, I bought the components and the memory leak doesn't appear anymore, that's VERY GOOD.

You have trouble with your trial version but NOT with the full version.

Thank you for your replies and hope you have a nice day

Marco J.

Ikar
Posts: 1693
Joined: Thu 28 Oct 2004 13:56

Re: Problem solved

Post by Ikar » Tue 14 Dec 2004 08:13

Thank you for information, we'll try to solve the problem.

Post Reply