Avatar billede martin_andersen Nybegynder
10. december 2003 - 13:48 Der er 3 kommentarer og
1 løsning

GetMem - FreeMem

Jeg er løbet ind i et lille problem med hensyn til alloc og dealloc af hukommelse. Her er et eks:

Funktion til at læse en stump tekst i en stor tekstfil.
På forhånd ved jeg hvor meget jeg skal læse og hvor jeg skal starte.
--------------------------------------------------------
Function ReadRecord(Rec: PFixRecord; Stream: TFileStream): String;
var
  Buffer: Pchar;

begin
  Buffer := NIL;
  try try
      Stream.Position := Rec^.StartLocation;
      GetMem(Buffer, Rec^.EndLocation - Rec^.StartLocation);
      Stream.ReadBuffer(Buffer^, Rec^.EndLocation - Rec^.StartLocation);
      Result := StrPas(Buffer);
  finally
      if Assigned(Buffer) then
        FreeMem(Buffer);
  end;

  except
      on E: Exception do
        Raise Exception.create('Error in readrecord: ' + Rec^.Identification + ' : ' + E.message);
  end;
end;
--------------------------------------------------------

Ovenstående funktion kaldes i en lykke, således at jeg læser flere blokke efter hinanden.

Dette virker ok MEN:
I enkelte tilfælde indeholder bufferen noget tekst fra forgående læsning efter mit kald til GetMem(). Når jeg så læser med TFileStream.ReadBuffer bliver bufferen fyldt med den korrekt tekst fra filen efterfuldt af det der står i bufferen i forvejen??? 

Hved gør jeg galt?
Avatar billede dkn Nybegynder
10. december 2003 - 16:56 #1
måske du skulle prøve med FillMem så alle bytes bliver slettet
Avatar billede martin_andersen Nybegynder
10. december 2003 - 17:05 #2
Jeg har forsøgt....
Jeg tror der er noget helt galt med min kode.

Jeg har dog fået det til at fungere med nedestående funktion:
-------------------------------------------------------------------------
Function TFixFileControl.ReadRecord(Rec: PFixRecord; Stream: TFileStream; RecordBuf: TStringList): Boolean;
var
  RecStream: TMemoryStream;

begin
  Buffer := NIL;
  try try
      RecStream := TMemoryStream.Create();
      Stream.Seek(Rec^.StartLocation, soFromBeginning);
      RecStream.CopyFrom(Stream, Rec^.EndLocation - Rec^.StartLocation);
      RecStream.Seek(0, soFromBeginning);
      RecordBuf.Clear;
      RecordBuf.LoadFromStream(RecStream);
  finally
      if Assigned(RecStream) then
        RecStream.Free;
  end;

  except
      on E: Exception do
        Raise Exception.create('Error in readrecord: ' + Rec^.Identification + ' : ' + E.message);
  end;
end;
-------------------------------------------------------------------------
Avatar billede hrc Mester
11. december 2003 - 12:18 #3
Mht. dit første eksempel så mangler du at allokere een byte ekstra og skrive en #0 i den, så strpas ved hvor strengen stopper; Strpas læser jo en pchar som skal termineres.

      Size := Rec^.EndLocation - Rec^.StartLocation + 1;
      GetMem(Buffer,Size);
      Buffer[Size - 1] := #0;


Vil i øvrigt anbefale at smække en fillchar ind efter allokeringen. Jeg aner ikke hvor mange clock cycles sådan en kommando kommer til at koste, men det er en god praksis at nulstille alt man allokerer - lært af nød...
Avatar billede martin_andersen Nybegynder
11. december 2003 - 13:11 #4
Det er rigtigt..... Det er sikkert derfor at bufferen blev større i nogle tilfælde. Jeg prøver det senere...tak for hjælpen.

Mit andet eksempel har vist sig at være lidt hutigere til formålet, og hvis jeg derudover skal kalde fillchar, så tror jeg at jeg holder mig til denne løsning.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester