Память, выделенная ClientDataSet, не освобождается даже после запуска методов EmptyDataSet, Close и даже Free. - PullRequest
0 голосов
/ 30 мая 2018

У меня есть приложение, которое содержит ClientDataSet, подключенное к DataSetProvider, которое подключено к TIBQuery ( Delphi 6 ).

Я запускаю несколько запросов и послев каждом из них я запускаю методы EmptyDataSet, Close и Free.

Например:

procedure TAggregator.Load(ASql: string);
begin
  try
    FQry.SQL.Text := ASql;
    FCds.SetProvider(FDsp);
    FCds.Open;
    FCds.EmptyDataSet;
    FCds.Close;
  except
    on e: Exception do
      raise e;
  end;
end;

Это два файла из моего минимального примера приложения, чтобы воспроизвести проблему:

program CdsConsumptionTest;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  IBDatabase,
  uAggregator in 'uAggregator.pas';

var
  database: TIBDatabase;
  transaction: TIBTransaction;
  aggregator: TAggregator;
  tables: TStringList;
  index: integer;

begin
  try
    try
      database := TIBDatabase.Create(nil);
      transaction := TIBTransaction.Create(nil);
      try
        database.DefaultTransaction := transaction;
        database.Params.Values['user_name'] := 'SYSDBA';
        database.Params.Values['password'] := 'masterkey';
        database.SQLDialect := 3;
        database.LoginPrompt := false;
        database.DatabaseName := 'C:\bases\17011\BASE.GDB';

        tables := TStringList.Create;
        aggregator := TAggregator.Create(database);
        try
          database.GetTableNames(tables);

          Writeln('Connection successful!');
          Write('Press ENTER to continue ...');

          // After that you can see the memory being increased and no longer released
          Readln;

          for index := 0 to pred(tables.Count) do
          begin
            aggregator.Load('select * from ' + tables[index]);
          end;
        finally
          tables.Free;
          aggregator.Free;
        end;

      finally
        database.Free;
        transaction.Free;
      end;
    except
      on e:Exception do
      begin
        Writeln('');
        Writeln('ERROR! ' + e.Message);
        Writeln('');
      end;
    end;
  finally
    Write('Process completed! Press ENTER to exit ...');
    Readln;
  end;
end.

и ...

unit uAggregator;

interface

uses
  IBQuery, DBClient, Provider, IBDatabase, SysUtils;

type
  TAggregator = class
  private
    FQry: TIBQuery;
    FCds: TClientDataSet;
    FDsp: TDataSetProvider;
  public
    constructor Create(AIBDatabase: TIBDatabase); reintroduce;
    destructor Destroy; override;
  public
    procedure Load(ASql: string);
  end;

implementation

{ TAgregador }

constructor TAggregator.Create(AIBDatabase: TIBDatabase);
begin
  inherited Create;
  FQry := TIBQuery.Create(nil);
  FQry.Database := AIBDatabase;

  FDsp := TDataSetProvider.Create(nil);
  FDsp.DataSet := FQry;

  FCds := TClientDataSet.Create(nil);
  FCds.SetProvider(FDsp);
  FCds.PacketRecords := -1;  
end;

destructor TAggregator.Destroy;
begin
  FCds.Free;
  FDsp.Free;
  FQry.Free;
  inherited;
end;

procedure TAggregator.Load(ASql: string);
begin
  try
    FQry.SQL.Text := ASql;
    FCds.SetProvider(FDsp);
    FCds.Open;
    FCds.EmptyDataSet;
    FCds.Close;
  except
    on e: Exception do
      raise e;
  end;
end;

end.

Когда я запускаю приложение, я вижу, что выделено много памяти.
После нажатия ENTER, чтобы запустить запросы, которые я вижу в задаче WindowsДиспетчер того, что память увеличивается и никогда не освобождается.
До тех пор, пока процесс не достигнет точки, в которой мне нужно нажать клавишу ВВОД, чтобы завершить работу приложения, и до тех пор память, которая была выделена (даже после освобождения от ClientDataSet), не освобождается..

В этом небольшом примере это не является большой проблемой.
Но в моем реальном приложении возникает исключение типа Out Of Memory.

Как я могу решитьэтот прoblem?


РЕДАКТИРОВАТЬ

Тестирование с FastMM4 Я получил следующий отчет:

FastMM4 Report

Что яне понимаю.

...