powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Утечка памяти при Canvas.Draw(0,0,bmp)
18 сообщений из 18, страница 1 из 1
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816520
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!
Непонятная хренотень происходит.

Win10 64, 10.2 Tokyo.

Нарисовал наследника TPanel
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
TMyPanel = class(TPanel)
  protected
    procedure Paint; override;
  public
    property Canvas;
    procedure DrawData(const ACounter:Integer);
    .......
end;
....
procedure TMyPanel.Paint;
begin
  inherited;
end;



Передаю данные на отрисовку и наблюдаю, что за 4 часа данный проект сожрал почти 280 Мб оперативки по таск-менеджеру.

Код отрисовки:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
procedure TMyPanel.DrawData(const ACounter:Integer);
var
  i: integer;
  bm: TBitmap;
begin
    bm:=TBitmap.Create;
    try
      bm.PixelFormat:=pf24bit;
      bm.Height:=ClientHeight; //400
      bm.Width:=ClientWidth;  //250

      try
        bm.Canvas.Brush.Style:=bsClear;
        bm.Canvas.Font.Name:='Arial';
        bm.Canvas.Font.Style:=[fsBold];
        bm.Canvas.Font.Size:=20;
        bm.Canvas.TextOut(
          (bm.Width div 2)-(bm.Canvas.TextWidth(ACounter.ToString) div 2),
          (bm.Height div 2)-(bm.Canvas.TextHeight(ACounter.ToString) div 2),
          ACounter.ToString);

        Canvas.Draw(0,0,bm);
      except on E:Exception do
        raise Exception.Create('Error= '+e.Message);
      end;
    finally
      FreeAndNil(bm);
    end;



Если я закомментирую Canvas.Draw(0,0,bm); то оперативка будет в пределах 10 Мб долгое время (более 4 часов).

Обращение к DrawData происходит 1 раз в секунду. Если бы не было FreeAndNil, то размер потребляемой памяти бы также увеличивался каждый такт, а он растет какими-то скачками по 1-3 Мб то раз в минуту, то раз в 2-3 минуты.

Может у кого-то была подобная проблема?
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816525
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K,

А FastMM утечку показывает?
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816535
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asviridenkov,

забыл добавить, ни FastMM, ни EurekaLog ничего не показывают.
Она просто утекает.
Если FreeAndNil на bm комментирую, то Eureka сразу выдает инфу об утечке
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816565
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
TMyPanel = class(TPanel)
private
  FCounter: Integer;
protected
  procedure Paint; override;
public
  property Canvas;
  procedure DrawData(const ACounter: Integer);
end;
....
procedure TMyPanel.Paint;
var
  i: integer;
  bm: TBitmap;
begin
    inherited;
    bm:=TBitmap.Create;
    try
      bm.PixelFormat:=pf24bit;
      bm.Height:=ClientHeight; //400
      bm.Width:=ClientWidth;  //250

      try
        bm.Canvas.Brush.Style:=bsClear;
        bm.Canvas.Font.Name:='Arial';
        bm.Canvas.Font.Style:=[fsBold];
        bm.Canvas.Font.Size:=20;
        bm.Canvas.TextOut(
          (bm.Width div 2)-(bm.Canvas.TextWidth(FCounter.ToString) div 2),
          (bm.Height div 2)-(bm.Canvas.TextHeight(FCounter.ToString) div 2),
          ACounter.ToString);

        Canvas.Draw(0,0,bm);
      except on E:Exception do
        raise Exception.Create('Error= '+e.Message);
      end;
    finally
      FreeAndNil(bm);
    end;
end;

procedure TMyPanel.DrawData(const ACounter:Integer);
begin
  FCounter := ACounter;
  Refresh;
end;
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816578
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Супер!
Я этот вариант подставления вместо отдельной процедуры даже не рассматривал в запаре :) т.к. казалось что какая разница откуда рисовать на канве из OnPaint или соседней процедуры.
За 15 минут прирост составил около 400 Кб, что не очень существенно.
Естественно я буду и дальше наблюдать за процессом, но интересно, почему такое поведение?
Не хватало Refresh?
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816589
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2Kинтересно, почему такое поведение?
Не хватало Refresh?Нет. В моем случае отрисовка происходит тогда, когда система посчитает нужным. А Refresh это уведомление системе, что данные изменились и нужно перерисоваться. У вас же перерисовка происходит всегда принудительно.

Вообще, любую кастомную отрисовку нужно производить только внутри обработчика WM_PAINT
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816602
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_любую кастомную отрисовку нужно производить только внутри обработчика WM_PAINTКак категорично-то.
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816613
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatКак категорично-то.Давай контр-пример
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816681
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Код: pascal
1.
2.
3.
4.
5.
procedure TMainForm.Timer1Timer(Sender: TControl)
begin
  // рисуем на BMP
  Image1.Picture.Bitmap.Assign(Bmp);
end;
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816685
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat
Код: pascal
1.
2.
// рисуем на BMP
  Image1.Picture.Bitmap.Assign(Bmp);

Это не "рисуем" а говорим TImage какую картинку мы хотим видеть. А когда система решит перерисовать TImage - заранее неизвестно
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816690
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Это не "рисуем" а говорим TImage какую картинку мы хотим видеть
Читай "рисуем на BMP" как "а тут предвариельно рисуем на битмап".

А когда система решит перерисовать TImage - заранее неизвестноНарисует как дойдет очередь сообщений.
Если надо "прям сразу" добавляем Image1.Repaint;
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816728
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatЕсли надо "прям сразу" добавляем Image1.Repaint;Правильно. А ТС вызывал рисование напрямую Kast2KCanvas.Draw(0,0,bm);
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816751
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Вообще, любую кастомную отрисовку нужно производить только внутри обработчика WM_PAINT Это не так.
Во-первых, рисование в буферах (на том же битмапе) ничем не отличается от рисования в окнах. А там, понятное дело, никаких WM_PAINT-ов нет.
Во-вторых, если бы это было так, MS не стал бы городить огород с GDI-batch-ами, которые внутри BeginDraw..EndDraw просто не используются.

У автора, я сильно подозреваю, проблемы с утечками из-за многопоточности, забыл залочить канву битмапа.
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816911
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
А зачем каждый раз заново создавать Bitmap внутри процедуры, а потом его уничтожать ?
Не проще создать его один раз в Create с нужными размерами и настройками,
а в самой процедуре просто очищать его и рисовать то, что надо ?
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816930
Сергей N
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
М-да... Создать битмап для простой отрисовки надписи в середине канвы, использовать при этом два защищаемых блока, уничтожить в конце и поиметь при этом проблемы... Что-то тут не так.

Куда катится мир.
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39816946
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
defecator,

нормально, только щас для этого есть спец функция, поделку в виде TBitmap явно не стоит использовать

предложение Соколинский Борис скорее всего верно, что-то автор недоговаривает
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39817074
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский БорисВо-первых, рисование в буферах (на том же битмапе) ничем не отличается от рисования в окнах.Кроме того факта, что битмап отрисовывается именно тогда, когда указал программист, а не решила система. И какой смысл рисовать окно с частотой 1000 раз в секунду, если система успеет отрисовать только 50? Кроме того, отрисовка окна вне WM_PAINT будет приводить к затиранию рисунка накладывающимися окнами
...
Рейтинг: 0 / 0
Утечка памяти при Canvas.Draw(0,0,bmp)
    #39817107
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,
это не является доказательством тезиса, на который я возражал:
любую кастомную отрисовку нужно производить только внутри обработчика WM_PAINT.

Прорисовка, скажем, прямоугольника выделения курсором - тоже кастомная отрисовка, и совсем необязательно ради нее городить сложную схему для встраивания в BeginDraw..EndDraw.
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Утечка памяти при Canvas.Draw(0,0,bmp)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]