Wyciek pamięci

0

Witam. Piszę gierkę pod Delphi 7 i mam pewien problem. Otóż w trakcie gry, gdy minie odpowiednia ilość czasu, wywala mi EOutOfResources (Nieprawidłowe dojście). Po krótkim debugowaniu, odkryłem iż problem występuje gdy liczba obiektów GDI osiągnie 10000 (!!!), czyli coś się nieprawidłowo czyści. Po dalszych poszukiwaniach odkryłem że jest to problem z procedurą

 
procedure TSHIPS_Asteroide.AnimationNext;
var BMP: TBitmap;
    Recta: TRect;
begin
  Inc(ANI_Frame);
  if ANI_Frame>16 then ANI_Frame:=1;
  Self.GUI_Bitmap.LoadFromResourceName(hInstance,'IBMP_'+IntToStr(50+ANI_Frame));
  Self.GUI_Bitmap.TransparentColor:=clBlack;
  Self.GUI_Bitmap.Transparent:=True;
  case Self.Kind of
       0: begin end;
       1: Self.ChangeRGB(GUI_Bitmap,50,-50,-50);
       2: Self.ChangeRGB(GUI_Bitmap,-80,50,-50);
       3: Self.ChangeRGB(GUI_Bitmap,-80,-60,50);
       4: Self.ChangeRGB(GUI_Bitmap,-100,-40,30);
       5: Self.ChangeRGB(GUI_Bitmap,-100,-50,100);
       6: Self.ChangeRGB(GUI_Bitmap,-30,45,60);
       7: Self.ChangeRGB(GUI_Bitmap,-30,-80,60);
       8: Self.ChangeRGB(GUI_Bitmap,-10,30,20);
  end;
  if Faza>0 then
  begin
  BMP:=TBitmap.Create;
  Recta.TopLeft.X:=0;
  Recta.TopLeft.Y:=0;
  Recta.BottomRight.X:=Self.GUI_Bitmap.Width div (Faza*2);
  Recta.BottomRight.Y:=Self.GUI_Bitmap.Height div (Faza*2);
  BMP.Assign(Self.GUI_Bitmap);
  BMP.Width:=Recta.BottomRight.X;
  BMP.Height:=Recta.BottomRight.Y;
  BMP.Canvas.StretchDraw(Recta,Self.GUI_Bitmap);
  Self.GUI_Bitmap.FreeImage;
  Self.GUI_Bitmap.Assign(BMP);
  BMP.Free;
  Self.Area:=Rect(-1*(GUI_Bitmap.Width div 2),-1*(GUI_Bitmap.Height div 2),
                  (GUI_Bitmap.Width div 2),(GUI_Bitmap.Height div 2));
  end;
  Self.GUI_Alpha:=0;
end;

Co najciekawsze, gdy wezmę w klamrę
BMP.Canvas.StretchDraw(Recta,Self.GUI_Bitmap);
problem nie występuje i wszystko ładnie się czyści.
I tu mam pytanie: czy to przeoczenie twórców Delphi, czy ja mam jakiś paskudny błąd w tej procedurce ?

Mam Delphi 7 Personal, WinXP Home

EDIT: Winę nie ponosi sam StretchDraw gdyż gdy zastosowałem alternatywną funkcję do skalowania, również był podobny problem. Oznacza to, że za wycieki odpowiada Canvas. Tylko czy nie powinien on być zwalniany z pamięci przez BMP.Free ?

EDIT2: Problem rozwiązany. Wystarczyło umieścić Self.GUI_Bitmap.Dormant; Temat do zamknięcia

0

generalnie żeś poszalał z tym kodem

  1. nie wiem ile razy na sekundę odrysowujesz, a co za tym idzie odczytujesz bmp z zasobów ale pewnie przynajmniej kilkanaście. Nie pomyślałeś aby wczytać te bmp raz, na początku, np. do tablicy czy listy?
  2. to samo z bmp tymczasową - nie pomyślałeś aby tworzyć ją RAZ i cały czas z niej korzystać?
  3. ten kod jest bez sensu
  BMP.Assign(Self.GUI_Bitmap);
  BMP.Width:=Recta.BottomRight.X;
  BMP.Height:=Recta.BottomRight.Y;
  BMP.Canvas.StretchDraw(Recta,Self.GUI_Bitmap);

bmp.Assign robi

  • ustawia wymiary bmp takie jak gui_bitmap
  • kopiuje zawartość płótna gui_bitmap do bmp
  • i pozostałych właściwości też
    następnie zmieniasz rozmiary bmp
    i na końcu i tak zamazujesz to co "narysowało" assign

Więc się pytam po co ten assign???

  1. żeby zmienić rozmiar bmp nie potrzeba ich wcale dwóch!
bmp.Canvas.StrechDraw(rect, bmp);
bmp.Width := rect.Right - rect.Left;
bmp.Height := rect.Bottom - rect.Top;
  1. to też jest jakieś dziwne podejście Recta.TopLeft.X:=0; - Recta.Left i Recta.Top nie działa??

Ogólnie rzecz biorąc ten kod, który dałeś jest mocno zakręcony i zbędne jest tam jakieś 2/3

1 użytkowników online, w tym zalogowanych: 0, gości: 1