У меня есть приложение, которое содержит 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](https://i.stack.imgur.com/dRyax.png)
Что яне понимаю.