Форум: "Основная";
Текущий архив: 2004.10.17;
Скачать: [xml.tar.bz2];
Внизутечка памяти Найти похожие ветки
← →
misha123 (2004-09-24 16:56) [0]Доброго дня.
Вот написал маленькую программку для просмотра каталога картинок. В папке лежат файлы, разложенные по другим папкам-группам, при хождении по дереву 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 image<>nil 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) список файлов, лежащих в указанной папке.
Спасибо за возможные ответы :)
← →
Iconka © (2004-09-24 17:03) [1]Используй MemCheck. Узнаешь есть ли утечка или нет.
Что это - ищи в google - модуль.
← →
Гаврила © (2004-09-24 17:04) [2]Есть специальные тузлы, которые показывают место утечки.
ты кстати с чего взял, что она происходит ? Если по task manager" у - то не верь
← →
Iconka © (2004-09-24 17:05) [3]
> с чего взял, что она происходит ?
Под системным блоком появилась небольшая лужа.
:)
← →
Lin7 (2004-09-24 17:15) [4]Есть хорошая утилита MemProof - находит утечки и показывает место в сырце. Была фришной.
Ищи на http://www.automatedqa.com
← →
misha123 (2004-09-24 17:17) [5]С чего я взял :) - в таск манагере - 6 (!) мб занимает программа, да и в росте не останавливается при очередном выборе ноды... Легко разрастается до 20-и и выше...
image:=TImage.Create(form1);
- даже понятно где утечка. В цикле креат стоит. Но если я его за пределы выношу - все картинки отображаются как одна и та же.....
← →
clickmaker © (2004-09-24 17:22) [6]
> [5] misha123 (24.09.04 17:17)
> image:=TImage.Create(form1); - даже понятно где утечка.
> В цикле креат стоит. Но если я его за пределы выношу - все
> картинки отображаются как одна и та же.....
Дык ты делай Free по необходимости
← →
misha123 (2004-09-24 17:36) [7]Ага я делаю, но image переменная глобальная - в обработчике события отрисовки листбокса тогда ничего отрисоваться не может - image-то nil. Варианты уже попробовал - если как локальные переменные объявлять image - утечка все-равно продолжается...
Вообще, странное какое-то поведение - один раз креат Image, а потом loadfromfile должен перегружать содержимое image
image.Picture.LoadFromFile(NodeName + giflist[i].namefile);
здесь имя файла меняется в цикле... но в список почему-то попадает одна и та же картинка....
← →
clickmaker © (2004-09-24 17:39) [8]
> [7] misha123 (24.09.04 17:36)
> Ага я делаю, но image переменная глобальная
> здесь имя файла меняется в цикле... но в список почему-то попадает одна и та же картинка....
Именно потому что глобальная.
Ты же в цикле ее lb_listarticul.Items.AddObject(giflist[i].namefile, image);
Вот в обработчике оттуда и доставай.
А когда они станут не нужны - всех их Free
← →
Basken (2004-09-24 17:48) [9]Создай контейнер TObjectList куда и запихивай картинки и при необходимости доставай их оттуда....
Images: TObjectList
← →
misha123 (2004-09-24 18:07) [10]to clickmaker :
Обработчик shelllistview: там как раз и стоит free - не помогает
А в обработчике листбокса они и так достаются....
← →
clickmaker © (2004-09-24 18:14) [11]
> [10] misha123 (24.09.04 18:07)
Ты и правда не понимаешь? В обработчике shelllistview ты убиваешь ГЛОБАЛЬНУЮ переменную, а локальные в Objects остаются жить. И ты потом на их место пишешь новые
← →
misha123 (2004-09-24 18:29) [12]to Basken - а чем плох listbox - точно так же хранит стринг и связанный с ним объект? Зачем я буду еще чего-то генерить?
← →
Defunct © (2004-09-24 18:45) [13]> image:=TImage.Create(form1);
Зачем это? И где вы убиваете все созданные Image?
Почему нельзя просто создать Bitmap?
← →
misha123 (2004-09-28 13:13) [14]to Defunct: в битмап нельзя, - использую гиф картинки...
в общем я почти разобрался - теперь пишу объекты в вектор, а потом по нему прохожусь и убиваю. Сильная утечка исчезла (понятное дело :) ). Теперь осталась слабая.
Что выяснил (использую tshelltreeview ): даже если комментирую вызов своей процедуры формирования списка и процедуры отрисовки листбокса (т.е. событие onclick для tshelltreeview остается, но в нем НИЧЕГО не происходит) - все-равно при щелчках по узлам потихоньку, но прога в памяти разрастается.
Что это? Глюк этого компонента?
← →
Amoeba © (2004-09-28 13:33) [15]
> Сильная утечка исчезла (понятное дело :) ). Теперь осталась
> слабая.
А с помощью чего установлен этот факт? Если по показаниям TaskManager - то снова читай пост:
Гаврила © (24.09.04 17:04) [2]
← →
zhe (2004-09-28 17:21) [16]убери строку
image:=TImage.Create(form1);
у тебя идёт накопление "бесхозных обьектов TImage в памяти". создай image ОДИН раз в начале рантайма. делай с ним всё, что хочешь. в конце рантайма просто FreeAndNil(image)
← →
zhe (2004-09-28 17:24) [17]есть ещё вариант: сделать image локальным объектом и просто добывлять в список. на деструкторе списка освобождаешь все элементы коллекции картинок. так вроде даже лучше... насколько я допёр ситуацию
← →
misha123 (2004-09-29 18:01) [18]to zhe - если убрать - то в листбокс пишется указатель и соответственно когда в цикле я гружу в эту переменную новую картинку - указатели будут ссылаться все-время на новую картинку... - результат: список из всех одинаковых картинок (последняя загруженная картинка..).
Короче, с этим проблем нет - все уже сделал - ПРОБЛЕМА №2:
в обработчике onclick (где все и происходит) компонента TShellTreeView все комментирую, т.е. он вызывается но ничего не делает. Результат - смотрю в таскманагер - при каждом щелчке память потихоньку разрастается ~по 8 Кбайт. Т.е. я вообще выключил все написанное мной, а трабл остался...
to Amoeba: почему верить нельзя и чему тогда верить?
За ответы спасибо.
← →
misha123 (2004-09-30 11:16) [19]Еще ма-аленький вопрос... :)
потестировал программку на разных компах, выяснил: что на одной из машин (на остальных все в порядке) программа при закрытии не выгружается из памяти, форма закрывается, а в процессах программа остается. Причем уже вручную в обработчике formclose после дестроя всех моих объектов сказал application.terminate - не помогает.
Это уже глюк ОС? Как с этим бороться?
← →
Amoeba © (2004-09-30 15:49) [20]В TaskManager, как уже об этом говорилось не раз, никогда не смотри - он тебе реальной картины не покажет - ну не способен он на это. Утечки памяти следует отлавливать ТОЛЬКО С ПОМОЩЬЮ специально предназначенных средств! Простейшее из них - MemCheck
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=944
Более слоное и мощное (причем тоже бесплатное) - MemProof
← →
misha123 (2004-10-01 12:11) [21]спасибо еще раз
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.10.17;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.036 c