Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Жесткая утечка памяти...


Автор: Coocky 16.4.2005, 16:47
Понеслось.Скоро буду возвращать прогу!Заказчик зол.
У меня на экран выводится картинка ,читаемая из файла.
После 2 х часов работы,по словам заказчика картинка не грузится(не отображается)
Ну я начил тестит.Сделал прогу.Задал таймер и начал выводит.Оказалось картинка весом 332Кб пропадает после 142 загрузки.Весом 93Кб после 543 раза.Что делать?
Вот код
Код

HBITMAP LoadAnImage(char* FileName)
   {
   // Use IPicture stuff to use JPG / GIF files
   IPicture* p;
   IStream* s;
   IPersistStream* ps;
   HGLOBAL hG;
   void* pp;
   FILE* fp;


   // Read file in memory
   fp = fopen(FileName,"rb");
   if (!fp)
   return NULL;

   fseek(fp,0,SEEK_END);
   int fs = ftell(fp);
   fseek(fp,0,SEEK_SET);
   hG = GlobalAlloc(GPTR,fs);
   if (!hG)
      {
      fclose(fp);
      return NULL;
      }
   pp = (void*)hG;
   fread(pp,1,fs,fp);
   fclose(fp);

   // Create an IStream so IPicture can
   // CreateStreamOnHGlobal(hG,false,&s);
   if (!s)
      {
      GlobalFree(hG);
      return NULL;
      }

   OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);

   if (!p)
      {
      s->Release();
      GlobalFree(hG);
      return NULL;
      }
   s->Release();
   GlobalFree(hG);

   HBITMAP hB = 0;
   p->get_Handle((unsigned int*)&hB);

   // Copy the image. Necessary, because upon p's release,
   // the handle is destroyed.
   HBITMAP hBB = (HBITMAP)CopyImage(hB,IMAGE_BITMAP,0,0,
                                    LR_COPYRETURNORG);

   p->Release();
   return hBB;
   }


Я слаб в функциях АПИ.Помогите.Ничего не могу найти.Где утечка?Вроде явного выделения памяти нет...
Делал уже и свой класс.В Функции рисования создавал обьект.Из выхода все ж должно было уничтожится вместе с обьектом.
Хелп!
Да ,еще при загрузке в таймере,при тесте,жестко "летит" оперативка.
Добавлено @ 16:49
Забыл
библиотеки #include <olectl.h> and <ole2.h>

Автор: maxim1000 16.4.2005, 19:41
Цитата
Вроде явного выделения памяти нет...

GlobalAlloc - явное выделение памяти

попробуй вместо его использования выделить память один раз и навсегда
это даст информацию о том, является ли GlobalAlloc причиной утечки

P.S.
что бросилось в глаза:
1. s перед проверкой не инициализируется (или вместо комментариев должен быть какой-то код?)
2. в область памяти под hG что-то считывается, но потом не используется (в том числе и pp)

Автор: Coocky 16.4.2005, 19:48
maxim1000
Цитата
s перед проверкой не инициализируется (или вместо комментариев должен быть какой-то код?)

Похрену...Я уже и нули присваивал.Так еще под 7.0 пишу.Обьявляю в классе.Студия сама инициализирует..
Цитата
2. в область памяти под hG что-то считывается, но потом не используется (в том числе и pp)

Ну и?Что делать?
Цитата
попробуй вместо его использования выделить память один раз и навсегда

Как?
Добавлено @ 19:51
Код

// CreateStreamOnHGlobal(hG,false,&s);

Цитата
s перед проверкой не инициализируется (или вместо комментариев должен быть какой-то код?)

Да раскоментировать надо.Забыл.Здесь забыл.

Автор: Coocky 16.4.2005, 20:07
Пацаны,ну худею уже от нервного напряга!

Автор: maxim1000 17.4.2005, 15:04
тогда такой вопрос: программа работает?
просто если работает, можно начинать отсекать ненужный код, что-то менять
если процедура не работает и к тому же позволяет утекать памяти, надо просто написать ее по-другому...

Автор: Coocky 17.4.2005, 19:10
maxim1000
еще раз перечитай.
Все работает,но до определеного времени.Что отсекать?

Автор: maxim1000 17.4.2005, 19:45
попробуй убрать все, что имеет отношение к hG
у меня почему-то сильное ощущение, что оно только выделяется и освобождается

Автор: chipset 17.4.2005, 19:53
Не вижу чтобы указатель pp освобождался.
Попробуй создать кучу размером в 93 кб функцией HeapCreate, выдели из неё память HeapAlloc'ом.
И покажи функцию рисования ;)

Автор: maxim1000 17.4.2005, 21:27
Цитата
Не вижу чтобы указатель pp освобождался

Цитата
Код

pp = (void*)hG;

а hG освобождается, вроде бы...
но я никак не могу понять, где информация, которая в него прочиталась, используется
а потому его лучше удалить, чтобы не мешал ошибку искать (кто его знает, может, и с ним связано)
если же чего-то недосмотрели (в смысле его использования), обязательно вылезет: программа ведь работающая, есть с чем сравнивать...

Автор: Coocky 17.4.2005, 21:28
Цитата
И покажи функцию рисования ;)

Функция возвращает обьект типа HBITMAP.А вот и фнкция pDC->BitBlt() smile
Цитата
Не вижу чтобы указатель pp освобождался

так вроде память-то под него не выделяется.Присваивается только
Цитата
Попробуй создать кучу размером в 93 кб функцией HeapCreate, выдели из неё память HeapAlloc'ом.
smile
Цитата
попробуй убрать все, что имеет отношение к hG

Ок.Но чувствую проблемы...

Автор: maxim1000 17.4.2005, 23:10
Цитата
Ок.Но чувствую проблемы...

никаких проблем
есть 3 варианта:
1. программа станет работать без утечки памяти
2. программа будет работать так же, как и раньше
3. программа перестанет работать (или станет как-то совсем по-другому)

в первом случае проблем никаких - задача решена
во втором случае проблема остается, но функция становится более оптимальной
в третьем случае становится ясно, что работа как-то завязана на hG

Автор: Fire-Plug 18.4.2005, 08:44
Цитата(Coocky @ 16.4.2005, 19:48)
.Так еще под 7.0 пишу.Обьявляю в классе.

Сразу скажу - код не смотрел. Решение предлагается - радикальное.
Если под 7.0 студией, возьми ATL класс CImage. Поддерживает достаточное к-во графич. форматов. Из файла он читает сам (т.е. имеет метод CImage::Load(const char *fileName)).
Все что нужно сделать после чтения, это - инициировать событие paint для окна вывода и в его обработчике нарисовать:
Код

COutptWnd::OnPaint(...)
{
   CDC dc(this);
   // m_image - объект класса CImage, загруженный ранее
   m_image.draw(dc, x0, y0, width, height, [константа типа STRETCH]);
}
// где
class COutptWnd : public CWnd

Пример записал по памяти, т.к. VC7 y меня на работе, дома VC6 (нет CImage). Подобный код у меня работает не 1000 раз, а 15 раз в сек. на протяжении часов, а иногда и суток.
ЗЫ: понятно, что трудно наступить на горло собственной песне, но если проект горит- все средства хороши.

Добавлено @ 08:51
Да, кстати, CImage также имеет перегруженный оператор HBITMAP. Всё, о чем остается подумать, это куда поместить объект собственно CImage, чтобы он был виден в ф-ции, но существововал за ее пределами (если привед. выше ф-ция LoadAnImage() - это С-ф-ция, а не метод класса).

Автор: Sun 18.4.2005, 15:06
При вызове функции CopyImage в памяти выделяется место под картинку. После того как картинка уже не нужна - нужно очищать выделенную память через DeleteObject. У тебя в коде этого вызова нет. Наверно в этом и проблема утечки памяти.

Автор: Coocky 18.4.2005, 22:07
Попробую.Пока спасибо smile
Добавлено @ 22:11
Sun
Удалять hBB?

Автор: Sun 19.4.2005, 10:30
Цитата(Coocky @ 18.4.2005, 19:07)
Sun
Удалять hBB?

Конечно. После того как он стает не нужен. Это можно делать в другой функции, но делать нужно обязательно. В MSDN написано
Цитата

When you are finished using the resource, you can release its associated memory by calling one of the functions in the following table.

Resource Release function
Bitmap      DeleteObject
Cursor      DestroyCursor
Icon          DestroyIcon

The system automatically deletes the resource when its process terminates, however, calling the appropriate function saves memory and decreases the size of the process's working set.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)