Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

Течет ручей, бежит ручей. И ты ничья и я ничей.

Hello comp,

Сабж касается утечки памяти, связанные с SetBitmap, который работает в цикле.
Т.е. на кнопке
через цикл перерисовается картинка. 5 переменных HBITMAP, которые передаются
в SetBitmap, инициализируются
при создании кнопки. Попытки использовать DeleteObject приводят к стиранию картиночки
на кнопке. Такой
вот интересный случай.
Еще интересное наблюдение - утечки памяти определяю через таскменеджер
(там все время растет память, выделяемая
программой, когда перерисовывается картинка на кнопке), там же показывается быстрый
рост каких-то GDI handles.
Подскажите, люди, где про них почитать можно.

Ответить   Fri, 21 Apr 2006 12:59:18 +0400 (#540369)

 

Ответы:

Deni_S> Hello comp,

Deni_S> Сабж касается утечки памяти, связанные с SetBitmap, который работает
в цикле.
Deni_S> Т.е. на кнопке
Deni_S> через цикл перерисовается картинка. 5 переменных
Deni_S> HBITMAP, которые передаются
Deni_S> в SetBitmap, инициализируются
Deni_S> при создании кнопки. Попытки использовать
Deni_S> DeleteObject приводят к стиранию картиночки
Deni_S> на кнопке. Такой
Deni_S> вот интересный случай.
Deni_S> Еще интересное наблюдение - утечки памяти
Deni_S> определяю через таскменеджер
Deni_S> (там все время растет память, выделяемая
Deni_S> программой, когда перерисовывается картинка на
Deni_S> кнопке), там же показывается быстрый
Deni_S> рост каких-то GDI handles.
Deni_S> Подскажите, люди, где про них почитать можно.

Попробуё сделать таким-вот образом:
1 Создай переменную СBitmap *pOldBmp;
2 Вызывай функцию pOldBmp=SetBitmap(твой_рисунок);
3 Затем, в конце цикла
pDC->SelectObject( pOldBmp ); //где pDC- контекст рисования

Вроде, должно сработать.

Павел a.k.a BOER mailto:bo***@u*****.fm

Номер выпуска : 5287
Возраст листа : 945 (дней)
Количество подписчиков : 545
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/540780
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sun, 23 Apr 2006 12:48:44 +0300 (#540780)

 

Здравствуйте !

Наверно в отношении кнопок это не очень актуально, т.к.
кнопке изначально битмап не сопоставлен.
Однако, использование MFC-шных врапперов вообще, весьма упрощает
работу с GDI-объектами.
Напрмер, применительно к исходной задаче можно создать массив объектов
CBitmap, загрузить битмапы с помощью CBitmap::LoadBitmap, а когда
битмапы больше станут не нужны, просто убить весь массив (а если
он статически выделен - вообще ничего не делать). Тогда будут
вызваны деструкторы всех элементов - объектов CBitmap.
CBitmap наследован от CGdiObject. А в деструкторе CGdiObject производится
вызов CGdiObject::DeleteObject, в которой GDI объект уничтожается
при помощи ::DeleteObject.
То есть, код будет гораздо меньше, не надо особо заботится об удалении
GDI-объектов.

Ответить   Sun, 23 Apr 2006 22:00:25 +0400 (#540939)

 

Hello Ischuk и Victor,

Sunday, April 23, 2006, 1:48:44 PM, you wrote:

// Получаем DC для рисования
HDC hDC = ::GetDC (GetSafeHwnd());
// Выбираем свой HBITMAP в DC, запоминаем старый HBITMAP
HBITMAP hOldBit = (HBITMAP)SelectObject(hDC, NewBmp);
// Выбираем старый BITMAP в DC (освобождаем свой BITMAP из DC)
SelectObject(hDC, hOldBit);

// Удаляем BITMAP
DeleteObject (NewBmp);

// Освобождаем DC
::ReleaseDC (GetSafeHwnd(), hDC);

Вот если таким образом, то никаких утечек нет. Осталось выяснить почему на кнопке
ничего не вырисовывается :) Может неправильно задаю какие свойства кнопок.

Добавление перед SetBitmap'om конструкции
HBITMAP NewBmp=GetBitmap();
SetBitmap(NULL);
DeleteObject(NewBmp);
увеличивает толщину ручья (утечки памяти) в 2 раза.

Давай представим идеальный случай: в цикле крутятся 3 HBITMAP bit1, bit2, bit3
которые загружены при старте программы. Этот цикл надо прервать только перед
выходом программы. Какие шаманские действия с SetBitmap надо сделать, чтобы
не было утечек?

Ага. Нашел книжонку (Дэвида Круглински). Начал по-немногу заставлять себя
сидеть с ней в обнимку. Пока не помогает. Наверно, надо ее попробовать
открыть :) Так что скоро сам все пойму. Всем спасибо за ответы.

Ответить   Mon, 24 Apr 2006 21:40:49 +0400 (#541307)

 

Доброго...Эм, поры суток, Deni_S.

Вы писали 24 апреля 2006 г., 20:40:49:

Deni_S> // Получаем DC для рисования
Deni_S> HDC hDC = ::GetDC (GetSafeHwnd());
Вот тут, я не понял...Зачем те вызывать GetSafeHwnd она же (выдержка
из МСДН) Returns the window handle for a window. Returns NULL if the CWnd is
not attached to a window or if it is used with a NULL CWnd pointer.

Deni_S> // Выбираем свой HBITMAP в DC, запоминаем старый HBITMAP
Deni_S> HBITMAP hOldBit = (HBITMAP)SelectObject(hDC, NewBmp);
Deni_S> // Выбираем старый BITMAP в DC (освобождаем свой BITMAP из DC)
Deni_S> SelectObject(hDC, hOldBit);

Deni_S> // Удаляем BITMAP
Deni_S> DeleteObject (NewBmp);

Deni_S> // Освобождаем DC
Deni_S> ::ReleaseDC (GetSafeHwnd(), hDC);

static bool bLoadOne=true;
CBitmap *pOldBitmap;
CBitmap newBitmap;
if(bLoadOne)
newBitmap.LoadBitmap(IDB_BITMAP_ONE);
else
newBitmap.LoadBitmap(IDB_BITMAP_TWO);
CDC *pDC;
pDC=((CButton*)GetDlgItem(ID_KNOPKA))->GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC);
pOldBitmap=memDC.SelectObject(&newBitmap);
pDC->BitBlt(10,3,18,15,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBitmap);
bLoadOne=!bLoadOne;

Вот таким макаром у меня прокатило, вроде, без утечек...Попробуй и ты
так!

Павел a.k.a BOER mailto:bo***@u*****.fm

Номер выпуска : 5293
Возраст листа : 947 (дней)
Количество подписчиков : 544
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/541598
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 25 Apr 2006 14:18:16 +0300 (#541598)

 

Hello Ischuk,

Tuesday, April 25, 2006, 3:18:16 PM, you wrote:

Deni_S>> // Получаем DC для рисования
Deni_S>> HDC hDC = ::GetDC (GetSafeHwnd());

is

Все время без сбоев работало (для диалоговых окошек). Поясню, поскольку
это было написано в классе кнопки, то GetSafeHwnd() вовращало хэндл окошка кнопки.
::GetDC использовался апишный. Тут все нормально - проверял.

Вот он - свет в конце туннеля. Выручил, Павел - ручей перекрыт.
Только в конце ты забыл ReleaseDC (pDC); иначе утечки шли
и дальше (не зря я сидел с книгой в обнимку :)

Ответить   Wed, 26 Apr 2006 00:00:18 +0400 (#541822)

 

Hello Deni_S,

Monday, April 24, 2006, 9:40:49 PM, you wrote:

Я тут возводил всякие еретические кляузы на SetBitmap, простите, люди, милосердно.
Был неправ. Оказывается даже без SetBitmap(NULL); он нормально работает. Просто
в моем
случае туману напустила функция OnCtlColor, в которой постоянно криэйтился GDI
объект.

Ответить   Sun, 30 Apr 2006 22:36:22 +0400 (#543788)

 

Здравствуйте !

Эти переменные надо инициализировать, сохранять, пока ведется
работа (всякие SetBitmap-ы используются, и.т.д.)
Потом, когда битмапы больше не нужны, надо выбрать для кнопки
битмап SetBitmap(NULL) и уничтожить все битмапы при помощи DeleteObject.
Тогда не будет утечки ресурсов.
Вобщем, идеология работы с ресурсами GDI такая:
1. создал
2. выбрал куда то, при этом сохранив то, что там было ранее
Например, при выборе битмапа в совместимый контекст устройства,
надо сохранять дескриптор битмапа, который в нем уже выбран.
3. попользоваться
4. вернуть все обратно (старые битмапы выбрать туда, где они были раньше,
и.т.д.).
5. убить все созданные ресурсы

то есть убивать надо все что создавал, но при этом GDI-ресурс не должен
где то использоваться, а то может не убиться.
Например, SEtBitmap можно сделать не только кнопке, но и static-у, так
вот, static control выбирает этот битмап в совместимый контекст и если
после SetBitmap сделать DeleteObject, битмап не уничтожится и произойдет
утечка ресурсов.

GDI handles - дескрипторы GDI объектов (перьев, битмапов, кистей,
контекстов, и.т.д.). ОС имеет таблицу дескрипторов GDI объектов
в ней всего 16384 элемента. На процесс может быть выделено некоторое
максимально количесво ресурсов GDI. После этого функции типа
CreatePen, CreateBitmap, и.т.д. начнут возвращать NULL.
Максимальное количество ресурсов на процесс прописано где то в реестре.
Если несколько приложений откушают все ресурсы, система начнет глючить -
окна приложений перестанут перерисовываться, и.т.д.
Поэтому ресурсы надо освобождать. Порисовал - освободил.

В MSDN, наверно. Ну и всякие книжки по программированию в винде, где
про рисование упоминается.

Ответить   Sun, 23 Apr 2006 13:39:09 +0400 (#540817)

 

Здравствуйте!

Могу порекомендовать книгу Павла Румянцева
"Азбука программирования в Win32 API"

С уважением, AleX

Номер выпуска : 5291
Возраст листа : 946 (дней)
Количество подписчиков : 544
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/540993
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Mon, 24 Apr 2006 00:28:43 +0400 (#540993)