[Poinnters] Zwalnienie pamieci

0

Witam mam problem ze zwalnianiem pamieci i chce prosic was o pomoc.

BlockHeader, jest recordem
BlockEntries to dynamiczna tablica z recordu BlockEntry
pBlockEntries to pointer recordu BlockEntry

procedure Read(s : TStream);
var
  i : integer;
  Size : Integer;
begin
  s.ReadBuffer(BlockHeader, sizeof(BlockHeader));

  Size := BlockHeader.BlockCount * sizeof(TBlockEntry);

  SetLength(BlockEntries, BlockHeader.BlockCount);
  GetMem(pBlockEntries, Size);

  for i:=0 to BlockHeader.BlockCount do
  begin
    pBlockEntries := @BlockEntries[i];
    Inc(pBlockEntries);
  end;
  Dec(pBlockEntries, BlockHeader.BlockCount);

  s.ReadBuffer(pBlockEntries^, Size);
end;

Napisalem Klase wiec w destruktorze jest FreeMem(pBlockEntries) i oczywiscie inherited.

Niewiem czy to takie trudne ale FreeMem ani Dispose nie dziala w tym przypadku. Wywalo mi blad przy uwalnianiu. Blod nie pojawia sie gdy nie przypisze adresow pamieci dla BlockEntries. Probowalem przd FreeMem ustawic BlockEntries (tablice) na nil ale nie pomaga. Prosze bardzo o pomoc a jesli to raczej nie mozwlie to chcialbym wiedziec czy jest jakis inny sposob zeby wczytac dane do pointera a potem rozdzielic adresy do tablicy. Dzieki.

0
sasio napisał(a)

BlockHeader, jest recordem
BlockEntries to dynamiczna tablica z recordu BlockEntry
pBlockEntries to pointer recordu BlockEntry

Coś namieszałeś. Jeżeli BlockEntries jest zadeklarowany jako 'array of BlockHeader' to ta zmienna już jest wskaźnikiem i nie potrzebujesz żadnego innego wskaźnika na nią. Chyba, że chcesz mieć tablicę dwuwymiarową, ale i tak jest prostszy sposób: 'array of array of BlockHeader'. Tablicy dynamicznej przydzielasz pamięc poprzez SetLength, a zwalniasz ją poprzez przypisanie do niej nil'a.

0

lecz niemoge wczytac za pomoca funkcji Read lub ReadBuffer nic do dynamicznej tablicy. Dlatego najlepiej jest uzyc wskaznika ale po prostu nie uwalnia tej pamieci bo wywala blad. Niewiem moze ja po prostu czegos niewiem ale juz tyle sie nad tym glowilem ze musze kogos doswiadczonego zapytac.

0

Ok. Od początku. Po pierwsze masz wyciek pamięci w tej procedurze.

procedure Read(s : TStream);
var
  i : integer;
  Size : Integer;
begin
  s.ReadBuffer(BlockHeader, sizeof(BlockHeader));

  Size := BlockHeader.BlockCount * sizeof(TBlockEntry);

  SetLength(BlockEntries, BlockHeader.BlockCount);
  GetMem(pBlockEntries, Size); // Prosisz o pamięć i ją dostajesz wraz ze wskaźnikiem pBlockEntries

  for i:=0 to BlockHeader.BlockCount do // Chyba BlockCount-1
  begin
    pBlockEntries := @BlockEntries[i]; // Nadpisujesz wskaźnik pBlockEntries nie zwalniając poprzednio zaalokowanej pamięci !
    Inc(pBlockEntries);
  end;
  Dec(pBlockEntries, BlockHeader.BlockCount); // To w połączeniu z poprzednią pętlą jest bez sensu. Równie dobrze mogło by być pBlockEntries:=@BlockEntries[0] bez pętli;
  s.ReadBuffer(pBlockEntries^, Size);
end;

Kto Ci powiedział, że za pomocą ReadBuffer nie możesz pisać do tablicy dynamicznej?

type TBlockHeader = record
     BlockCount: integer;
     end;

     TBlockEntry = record
     zmienna2: byte;
     end;

var BlockHeader: TBlockHeader;
    BlockEntries: array of TBlockEntry;

var BlockHeader: TBlockHeader;
	BlockEntries: array of TBlockEntry;

procedure foo(s: TStream);
begin
s.ReadBuffer(BlockHeader, sizeof(TBlockHeader)); // Wczytujemy sobie nagłówek
SetLength(BlockEntries, BlockHeader.BlockCount); // Ustalamy ilość wierszy w tablicy dynamicznej
s.ReadBuffer(BlockEntries, BlockHeader.BlockCount*sizeof(TBlockEntry)); // Wczytujemy odpowiednią ilość bajtów do pamięci zaczynając od miejsca wskazującego przez BlockEntries
end;
0

tak tam powinno byc -1 moj blad i Od razu dzieki za "pBlockEntries:=@BlockEntries[0]" bo niewiedzialem ze wystarczy przypisac pierwszy element. Jeszcze raz dzieki za to. Lecz problem zostal przy uwalnianiu pamieci (w destruktorze) mam blad "Invalid pointer operation", a co do wczytywania do dynamicznej tablicy przez ReadBuffer sam sobie tak powiedzialem ze sie nieda bo gdy zrobie tak jak mi pokozales to po prostu kod sie zatrzymuje przy funkcji ReadBuffer. Nie wyswietla zadnego blady po prostu aplikacja nie rusza dalej i nic nie wczytuje do tablicy. Mozesz to sprawdzic piszac funcje kopiowania pliku i z uzyciem dynamicznej tablicy jako Buffor. Dzieki i mam nadzieje ze jakos pomozesz mi rozwiazac ten problem.

Edytowane:
Chyba rozwiazalem moj problem i to dzieki tobie. Sprobowalem zrobic ReadBuffer(BlockEntries[0], Size) i dziala. Jeszcze raz dzieki ;-) .

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