Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

утечка памяти [D7, WinXP]


Страницы:   1 2

misha123 ©   (2004-09-24 16:56:00) 

Доброго дня.

Вот написал маленькую программку для просмотра каталога картинок. В папке лежат файлы, разложенные по другим папкам-группам, при хождении по дереву shelltreeview в листбоксе отображаются картинки. Все хорошо, только при каждом щелчке по узлу группы дерева память, отведенная для программки разрастается. Код привожу:

Отрисовщик-обработчик листбокса:

procedure TForm1.ListBoxDrawItem;
var Offset: Integer;
   tb: boolean;
   s: string;
begin
with (Control as TListBox).Canvas do begin
  FillRect(Rect);
 if odSelected in State then begin
  Font.Color := clWhite;
  Font.Style := [fsBold];
 end;
  image:=TImage((Control as TListBox).Items.Objects[Index]);
  if imagenil then begin
   Draw(Rect.Left + 2, Rect.Top, image.Picture.Graphic);
   Offset := image.width + 6;
   TextOut(Rect.Left + Offset, Rect.Top + image.Height div 2, (Control as TListBox).Items[Index] + '   ¹' + inttostr(Index + 1));
  end;
end;
end;


Обработчик shelllistview:

procedure TForm1.stv_catalogClick(Sender: TObject);
var NodeName: string;
begin
NodeName:=stv_catalog.Selected.Text;

lb_listarticul.Clear;
cb_articuls.Clear;
image.Free;

NodeName:=path_catalog + NodeName + '\';
ShowItems(NodeName);


Формирование списка для отображения:

procedure TForm1.ShowItems;
var gifList: trGifList;
   i: integer;
   cursor: Tcursor;
begin
lb_listarticul.Cursor:=-11;
cb_articuls.Items.Clear;

gifList:=cProduct.FormFileListGif(NodeName);
 for i:=0 to length(giflist)-1 do begin
         image:=TImage.Create(form1);
         image.Picture.LoadFromFile(NodeName + giflist[i].namefile);
         delete(giflist[i].namefile, length(giflist[i].namefile)-3, 4);
         cb_articuls.Items.Add(giflist[i].namefile);
         lb_listarticul.Items.AddObject(giflist[i].namefile, image);
 end;
gifList:=nil;

lb_listarticul.Cursor:=0;
end;


image: TImage - объявлен глобально, при закрытии формы делается free.

gifList:=cProduct.FormFileListGif(NodeName); - формирует (в массиве; динамическом, но он в конце - nil) список файлов, лежащих в указанной папке.

Спасибо за возможные ответы :)


misha123   (2004-10-01 12:11:00) [1]

спасибо еще раз


Amoeba   (2004-09-30 15:49:00) [2]

В TaskManager, как уже об этом говорилось не раз, никогда не смотри- он тебе реальной картины не покажет - ну не способен он на это. Утечки памяти следует отлавливать ТОЛЬКО С ПОМОЩЬЮ специально предназначенных средств! Простейшее из них - MemCheck
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=944

Более слоное и мощное (причем тоже бесплатное) - MemProof


misha123   (2004-09-30 11:16:00) [3]

Еще ма-аленький вопрос... :)
потестировал программку на разных компах, выяснил: что на одной из машин (на остальных все в порядке) программа при закрытии не выгружается из памяти, форма закрывается, а в процессах программа остается. Причем уже вручную в обработчике formclose после дестроя всех моих объектов сказал  application.terminate - не помогает.

Это уже глюк ОС? Как с этим бороться?


misha123   (2004-09-29 18:01:00) [4]

to zhe - если убрать - то в листбокс пишется указатель и соответственно когда в цикле я гружу в эту переменную новую картинку - указатели будут ссылаться все-время на новую картинку... - результат: список из всех одинаковых картинок (последняя загруженная картинка..).
Короче, с этим проблем нет - все уже сделал - ПРОБЛЕМА №2:

в обработчике onclick (где все и происходит) компонента TShellTreeView все комментирую, т.е. он вызывается но ничего не делает. Результат - смотрю в таскманагер - при каждом щелчке память потихоньку разрастается ~по 8 Кбайт. Т.е. я вообще выключил все написанное мной, а трабл остался...

to Amoeba: почему верить нельзя и чему тогда верить?

За ответы спасибо.


zhe   (2004-09-28 17:24:00) [5]

есть ещё вариант: сделать image локальным объектом и просто добывлять в список. на деструкторе списка освобождаешь все элементы коллекции картинок. так вроде даже лучше... насколько я допёр ситуацию


zhe   (2004-09-28 17:21:00) [6]

убери строку
image:=TImage.Create(form1);

у тебя идёт накопление "бесхозных обьектов TImage в памяти". создай image ОДИН раз в начале рантайма. делай с ним всё, что хочешь. в конце рантайма просто FreeAndNil(image)


Amoeba   (2004-09-28 13:33:00) [7]


> Сильная утечка исчезла (понятное дело :) ). Теперь осталась
> слабая.

А с помощью чего установлен этот факт? Если по показаниям TaskManager - то снова читай пост:
Гаврила ©   (24.09.04 17:04) [2]


misha123   (2004-09-28 13:13:00) [8]

to Defunct: в битмап нельзя, - использую гиф картинки...
в общем я почти разобрался - теперь пишу объекты в вектор, а потом по нему прохожусь и убиваю. Сильная утечка исчезла (понятное дело :) ). Теперь осталась слабая.
Что выяснил (использую tshelltreeview ): даже если комментирую вызов своей процедуры формирования списка и процедуры отрисовки листбокса (т.е. событие onclick для tshelltreeview остается, но в нем НИЧЕГО не происходит) - все-равно при щелчках по узлам потихоньку, но прога в памяти разрастается.
Что это? Глюк этого компонента?


Defunct   (2004-09-24 18:45:00) [9]

> image:=TImage.Create(form1);

Зачем это? И где вы убиваете все созданные Image?

Почему нельзя просто создать Bitmap?


misha123   (2004-09-24 18:29:00) [10]

to Basken  - а чем плох listbox - точно так же хранит стринг и связанный с ним объект? Зачем я буду еще чего-то генерить?


clickmaker   (2004-09-24 18:14:00) [11]


> [10] misha123   (24.09.04 18:07)

Ты и правда не понимаешь? В обработчике shelllistview ты убиваешь ГЛОБАЛЬНУЮ переменную, а локальные в Objects остаются жить. И ты потом на их место пишешь новые


misha123   (2004-09-24 18:07:00) [12]

to clickmaker :
Обработчик shelllistview: там как раз и стоит free - не помогает
А в обработчике листбокса они и так достаются....


Basken   (2004-09-24 17:48:00) [13]

Создай контейнер TObjectList куда и запихивай картинки и при необходимости доставай их оттуда....

Images: TObjectList


clickmaker   (2004-09-24 17:39:00) [14]


> [7] misha123   (24.09.04 17:36)
> Ага я делаю, но image переменная глобальная
> здесь имя файла меняется в цикле... но в список почему-то попадает одна и та же картинка....

Именно потому что глобальная.
Ты же в цикле ее lb_listarticul.Items.AddObject(giflist[i].namefile, image);
Вот в обработчике оттуда и доставай.
А когда они станут не нужны - всех их Free


misha123   (2004-09-24 17:36:00) [15]

Ага я делаю, но image переменная глобальная - в обработчике события отрисовки листбокса тогда ничего отрисоваться не может - image-то nil. Варианты уже попробовал - если как локальные переменные объявлять image - утечка все-равно продолжается...

Вообще, странное какое-то поведение - один раз креат Image, а потом loadfromfile должен перегружать содержимое image

image.Picture.LoadFromFile(NodeName + giflist[i].namefile);

здесь имя файла меняется в цикле... но в список почему-то попадает одна и та же картинка....


clickmaker   (2004-09-24 17:22:00) [16]


> [5] misha123   (24.09.04 17:17)
> image:=TImage.Create(form1); - даже понятно где утечка.
> В цикле креат стоит. Но если я его за пределы выношу - все
> картинки отображаются как одна и та же.....

Дык ты делай Free по необходимости


misha123   (2004-09-24 17:17:00) [17]

С чего я взял :) - в таск манагере - 6 (!) мб занимает программа, да и в росте не останавливается при очередном выборе ноды... Легко разрастается до 20-и и выше...

image:=TImage.Create(form1);- даже понятно где утечка. В цикле креат стоит. Но если я его за пределы выношу - все картинки отображаются как одна и та же.....


Lin7   (2004-09-24 17:15:00) [18]

Есть хорошая утилита MemProof - находит утечки и показывает место в сырце. Была фришной.
Ищи на http://www.automatedqa.com


Iconka   (2004-09-24 17:05:00) [19]


> с чего взял, что она происходит ?

Под системным блоком появилась небольшая лужа.
:)


Гаврила   (2004-09-24 17:04:00) [20]

Есть специальные тузлы, которые показывают место утечки.
ты кстати с чего взял, что она происходит ? Если по task manager' у - то не верь


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо