Memory leak in MemDS

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
cis-wurzen
Posts: 75
Joined: Tue 04 Jan 2005 10:26

Memory leak in MemDS

Post by cis-wurzen » Sun 31 May 2009 11:15

There are memory leaks in MemDS and FastMM4 shows them in FullDebugMode. For the following example you'll get two leaks with a call stack like this

[System][@GetMem]
[CLRClasses][Marshal.AllocHGlobal]
[MemDS][TMemDataSet.AllocRecordBuffer]
[Db][TDataSet.SetBufListSize]

The example is of course no real life code, but it is similar to the real life code. The real life code is a TVirtualTable and a TDataSource on a TDataModule with the following conditions (without one of them it won't repeat):
- TDataSource is defined in the .dfm after the TVirtualTable
- the TVirtualTable won't be opened at runtime (either by streaming or by code)
- the TVirtualTable has data stored in the .dfm

In order to make the leaks disappear you can open the TVirtualTable or inherited TVirtualTable and call "SetBufListSize(0);" in the destructor. This bug very likely does also happen with other dataset's using MemDS.

Code: Select all

program MemDSVTLeak;

{$APPTYPE CONSOLE}

uses
  FastMM4,
  Classes,
  DB,
  VirtualTable;

{
  The memory leak disappears if you either define DISAPPEAR1
  or DISAPPEAR2. This are no workarounds - they just show the
  root of the problem!
}
{.$DEFINE DISAPPEAR1}
{.$DEFINE DISAPPEAR2}

{$IFDEF DISAPPEAR1}
type
  TVirtualTable = class(VirtualTable.TVirtualTable)
  public
    destructor Destroy; override;
  end;

destructor TVirtualTable.Destroy;
begin
  SetBufListSize(0);
  inherited Destroy;
end;
{$ENDIF DISAPPEAR1}

const
  DataArray: array [0..25] of Byte =
    (2, 0, 1, 0, 2, 0, 73, 68, 3, 0, 0, 0, 0, 0, 1, 0,
     0, 0, 4, 0, 0, 0, 1, 0, 0, 0);

var
  MS: TMemoryStream;
  vt: TVirtualTable;
  ds: TDataSource;
begin
  vt := TVirtualTable.Create(nil);
  try
    vt.FieldDefs.Add('ID', ftInteger);
    MS := TMemoryStream.Create;
    try
      MS.Write(DataArray, Length(DataArray));
      vt.LoadFromStream(MS, True);
      {$IFDEF DISAPPEAR2}
      vt.Open;
      {$ENDIF DISAPPEAR2}
    finally
      MS.Free;
    end;
    ds := TDataSource.Create(nil);
    try
      ds.DataSet := vt;
    finally
      ds.Free;
    end;
  finally
    vt.Free;
  end;
end.

Plash
Devart Team
Posts: 2844
Joined: Wed 10 May 2006 07:09

Post by Plash » Mon 01 Jun 2009 06:54

We have fixed this problem. The fix will be included in the next build of ODAC.

Post Reply