[Delphi] Problem ze zwalnianiem zasobów i EOutOfMemory

0

Piszę bardzo rozbudowany program i nie wiem czy poprawnie zwalniam w nim zasoby, ponieważ po kilkudziesięciu uruchomieniach go, program zaczyna coraz wolniej działać, a po pewnym czasie pojawia się błąd EOutOfMemory. Program korzysta z kilku tablic dynamicznych (globalne):

  KNr           : array of Word;
  KSta         : array of String[40];
  KKol          : array of Word;
  KWid         : array of Boolean;
  FileList       : array of String;
  FileDate     : array of TDate;
  TabImage   : array of TImage;
  PImage      : array of TImage;
  NImage      : array of TImage;
  Godzina      : array of array of TDateTime;
  Rect          : array of array of TRect;
  Kolor          : array of array of Byte;

a tak wygląda u mnie zwalnianie zasobów:

  • dla tablic typu array of array of ... wywołuję:
        for i:=0 to Length(Godzina)-1 do
        begin
        Godzina[i]:=nil;
        end;
        Godzina:=nil;
  • dla czcionek:
FontGodzina:=TFont.Create;
...
FontGodzina.Free;
  • dla array of TImage:
        for i:=0 to Length(Image)-1 do
        begin
        Image[i].Destroy;
        end;

dodam, że rysuję tylko po canvasie obrazka, a funkcja rysująca jest wywoływana z dll'a (dll ładowany statycznie i przekazuję do niego tylko uchwyt handle canvasa), obrazek ma duze rozmiary, bo około 120x(10000-1000) i tych komponentów image jest kilka.

  • dla bitmap:
b:=Tbitmap.Create;
...
b.Free;

no to chyba tyle, więc nie wiem właściwie co tutaj może powodować problemy, może problem jest ze zwalnianiem obrazków? Albo problem jest w czymś innym, nie wiem juz :-/

Jeśli ktoś wiec, co może powodować takie problemy z pamięcią, to prosze o pomoc [!!!] [!!!] [!!!]

0

Witam. Przedstawię Ci mój punkt widzenia. Generalnie nigdy nie używałem tablic otwartych do obsługi dużych struktur. Zawsze znałem liczbę elementów tablicy czy bazy danych. Całkiem niedawno pisałem program, do obsługi 30MB bazy danych i całość realizowałem procedurami GetMem, FreeMem, New, Dispose. Dzięki temu zawsze bilans pamięci zarezerwowanej i zerowej wynosił zero. Typy tablicowe deklarowałem na zasadzie:

type
 PDayReport   = ^TDayReport;
 TDayReport   = array [1..2] of TPressReport;
 PMonthReport = ^TMonthReport;
 TMonthReport = array [1..31] of TDayReport;
 PYearReport  = ^TYearReport;
 TYearReport  = array [1..12] of TMonthReport;
 PReport      = ^TReport;
 TReport      = array [1..8] of TYearReport;
var
 Repor :PYearReport;

Później używałem procedur

New(Report); // GetMem(Report, SizeOf(TReport));
Dispose(Report); // FreeMem(Report, SizeOf(TReport));

Operowanie wskaźnikami jest stosunkowo niebezpieczne (zawsze można zapomnieć ^) ale dużo wygodniejsze w użyciu.

Poza tym Borland nie zaleca bezpośredniego używania Imag1.Destroy, zalecane jest Image1.Free.

0

SetLength(tablica, 0);

0
  1. nie Image[i].Destroy; tylko Image[i].Free; albo lepiej FreeAndNil(Image[i]);
  2. jeśli tablica przechowuje typy proste (inty, double, itp) to wystarczy SetLength(tab, 0); tab := nil;
  3. jak masz tablicę np. imageów to najpierw każdy image.free a potem pkt2
0

Dzieki, popracuję nad tym, do pewnych rzeczy chyba jednak muszę używać tablic, bo program będzie korzystał z ich zawartości co minutę, więc nie wiem, czy jest sens ładowania na nowo tablicy i zwalniania jej, ale pomysl super, może sie przyda. Dzieki wszystkim

0

Po 1. Masz dynamiczne tablice obiektów, ale zwalniasz tylko obiekty, a tablice zostawiasz.
Zwalniać obiekty najlepiej powinieneś w pętli, jak napisałeś, z tym, że:

obiekt.free;
obiekt:=nil;

Natomiast tablicę dynamiczną zwalniasz:

tablica:=nil;

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