![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TClientDataSet и освобождение памяти [D7]
Jungle © (2009-03-31 12:06:00)Заметил такое поведение TClientDataSet: когда его очищаешь, память не освобождается.
Смотрел с помощью ProcessExplorer v11.21 (Sysinternals), а также при помощи FastMM (Fast Memory Manager v4.92).
В ProcessExplorer'е наглядно видно как при добавлении записей потребляемая память растёт, а при очистке не убывает. FastMM пишет при завершении приложения об утечках памяти - Unknown x N, где N - число записей в ClientDataSet.
Причём, еслиClientDataSet.LogChanges = false, то память не очищается вовсе, а если true, то чего-то очищается, но не до исходного состояния.
Если заполнять (устанавливать длину) и очищать динамический массив, то память нормально увеличивается и уменьшается.
Такое поведение нормально? И если нет, то возможно ли побороть?
salexn (2009-04-02 13:31:00) [1]> Jungle
Советую посмотреть в сторону SpeedMidasFix v1.2
hxxp://andy.jgknet.de/blog/?p=437
Jungle (2009-04-01 09:39:00) [2]Благодарю всех. Нашёл причину утечек с помощью UDebugMemoryLeak. Глупая ошибка new/dispose.
Сергей М. (2009-03-31 20:01:00) [3]
> оставлю пункт 10
Все в порядке. Никаких утечек нет.
Jungle (2009-03-31 15:57:00) [4]Сергей М.
Поскольку Close DS делается при каждом Clear DS, то оставлю пункт 10.
Вот новые результаты:
1. 4.8 Mb
2. 7.8 Mb
3. 6.3 Mb
4. 9.4 Mb
5. 35.5 Mb
6. 31.4 Mb
7. 8.7 Mb
8. 6.0 Mb
10. 5.5 Mb
Сергей М. (2009-03-31 15:41:00) [5]9. Close DS : что кажет PE ???
10. Сверни-разверни форму : что кажет PE ???
Jungle (2009-03-31 15:31:00) [6]sniknik
За трепло прошу прощения. Был не в себе :)
Чуток изменил код:
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
ClientDataSet1.DisableControls;
if ( not ClientDataSet1.Active ) then
begin
ClientDataSet1.CreateDataSet;
ClientDataSet1.Open;
end;
for i := 1 to 50000 do
ClientDataSet1.AppendRecord([i, 'lazha!']);
ClientDataSet1.EnableControls;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ClientDataSet1.DisableControls;
ClientDataSet1.EmptyDataSet;
ClientDataSet1.Close;
ClientDataSet1.EnableControls;
end;
Что наблюдается в ProcessExplorer'е:
1. После старта : 4.8 Mb
2. Fill DS : 7.2 Mb
3. Clear DS : 5.6 Mb
4. Fill DS : 9.3 Mb
5. Fill DS : 34.4 Mb
6. Clear DS : 5.0 Mb
7. Fill DS : 9.5 Mb
8. Clear DS : 6.8 Mb
Кстати, на этом маленьком проекте FastMM не ругается. Ругается на другом. Но именно после манипуляций с DataSet'ом. Если его не трогать - не ругается. Иных утечек тоже не показывает. Вот и не знаю - то ли я облажался, то ли одно из двух :)
Надо какой-нибудь другой менеджер памяти попробовать для чистоты эксперимента.
sniknik (2009-03-31 14:57:00) [7]> продемонстрировать свой профессионализм
это все давно в прошлом. да и был такой период недолго, после становиться пофигу.
почему не вижу Close у рекордсета? решил, что Delete физически удаляет запись? таки нет. их даже посмотреть можно (как то фильтром управляется, хотя не помны может это для ADORecordset-а, но принцип должен быть примерно тот же)
Jungle (2009-03-31 14:43:00) [8]sniknik
1. Видимо, действительно, нечего делать, ибо если бы было чем заняться - не писал бы неинформативные сообщения.
2. Допустим, мне действительно стыдно - ведь код не работает так как мне надо, но если у тебя всё нормально работает - тебе-то чего стесьняться? Наоборот - прекрасная возможность продемонстрировать свой профессионализм и утереть нос салаге.
Вывод: ты просто трепло.
3. Вот мой код.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, DBClient, Grids, DBGrids, GridsEh, DBGridEh;
type
TForm1 = class(TForm)
ClientDataSet1 : TClientDataSet;
ClientDataSet1f1 : TIntegerField;
ClientDataSet1f2 : TStringField;
DataSource1 : TDataSource;
Button1 : TButton;
DBGridEh1 : TDBGridEh;
Button2 : TButton;
Button3 : TButton;
Button4 : TButton;
btn1 : TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var ar: array of Integer;
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
ClientDataSet1.DisableControls;
for i := 1 to 50000 do
ClientDataSet1.AppendRecord([i, 'lazha!']);
ClientDataSet1.EnableControls;
ClientDataSet1.Cancel;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if ( ClientDataSet1.IsEmpty ) then exit;
ClientDataSet1.Last;
ClientDataSet1.Delete;
end;
procedure TForm1.Button3Click(Sender: TObject);
var i: Integer;
begin
ClientDataSet1.DisableControls;
ClientDataSet1.EmptyDataSet;
ClientDataSet1.EnableControls;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
SetLength(ar, 250000);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ClientDataSet1.LogChanges := False;
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
SetLength(ar, 0);
end;
end.
sniknik (2009-03-31 14:15:00) [9]> Я упомянул 2 инструмента - проверь.
делать больше нечего как бред проверять... ведь у тебя явно написан бред, раз ты его настолько стесняешься, что даже свой код для проверки не привел (проверять имеет смысл именно его).
а если я напишу не так как ты. и у меня все очистится? что дальше?
давай попробуем. вот считай проверил, результат - очищается! и?
Jungle (2009-03-31 13:55:00) [10]
> А TClientDataset-то тут причем ?
Массив я привёл в качестве иллюстрации ожидаемогоповедения TClientDataSet.
Т.е. при работе с массивом память резервируется и освобождается так, как я того ожидаю. А вот при работе с TClientDataSet всё не так.
Я упомянул 2 инструмента - проверь.
Сергей М. (2009-03-31 12:48:00) [11]А TClientDataset-то тут причем ?
Ты чего-то там шебуршишься с какими-то массивами, а "виноват", видите ли, TClientDataset?
Зашибсись логика)
Jungle (2009-03-31 12:30:00) [12]
> Какая длина ?
> Какого массива ?
Объявляю массив
var ar : array of integer;
Потом в программе задаю длину (по нажатию кнопки)
SetLength(ar, 250000);
При выполнении этого действия в ProcessExplorer'е видно, что используемая память увеличилась на 1Мб
Потом меняю длину (тоже по нажатию кнопки)
SetLength(ar, 0);
При выполнении этого действия в ProcessExplorer'е видно, что используемая память уменьшилась на 1Мб.
Сергей М. (2009-03-31 12:13:00) [13]
> Если заполнять (устанавливать длину) и очищать динамический
> массив
Какая длина ?
Какого массива ?