Hello!
I made a strange observation using Delphi 2.0:
It seems to me that Readln causes memory leakage.
1. I monitor memory usage using the appidle-method:
procedure tMainform.appidle;
begin
statusbar.panels[2].text := inttostr(getheapstatus.totalallocated div 1024)+' kbytes alloziert';
end;
2. I use the following class to handle (many) textfiles:
type tMyStringList = class(tList)
protected
anincrement : integer;
procedure grow;override;
public
constructor create;
procedure addstring(which : string);
procedure writestring(where : integer;which : string);
function getstring(which : integer):string;
procedure loadfromfile(const path : string);
procedure writetofile(const path : string; modus : tMystringlistfilemode);
destructor destroy;override;
property increment:integer read anincrement write anincrement;
property strings[which:integer]:string read getstring write writestring; default;
end;
everything works as expected, except for the loadfromfile-method:
procedure tMystringlist.loadfromfile;
var f : text;
bytesloaded,actlinelen,cnt : integer;
s :string;
textpuffer : array[0..4096] of byte;
tsr : tsearchrec;
begin
findfirst(path,faanyfile,tsr);
assign(f,path);
reset(f);
settextbuf(f,textpuffer);
try
bytesloaded := 0;
capacity := tsr.size div 60;
//guess how many lines the file will contain
if capacity < 128 then capacity := 128;
// the size of the list WILL grow later, so prepare here
while not eof(f)
do begin
if count >= capacity-8 then
begin
//guess how many lines are left to be read
actlinelen := bytesloaded div count;
capacity := (count+ ((tsr.size-bytesloaded) div actlinelen))+8
// add some extra lines
end;
readln(f,s);
bytesloaded := bytesloaded+length(s)+2; //fr Enter
addstring(s);
// ad line to the list
end;
finally
s.free;
findclose(tsr);
system.close(f);
end;
end;
The problem is that the statusbar reports significant memory leakage after
using this method. The amount of leakage increases with each call to
loadfromfile and seems to correspond with the length of the longest line
in each file. For test purposes I used blockread instead.
The following variation reads files in 128 byte chunks
(not exactly what I want, it is for test only). No memory
leakage occurs:
procedure tMystringlist.loadfromfile;
var f : file;
bytesloaded,actlinelen,cnt,dummy : integer;
s :string;
textpuffer : array[0..4096] of byte;
tsr : tsearchrec;
begin
findfirst(path,faanyfile,tsr);
assign(f,path);
reset(f,1);
//settextbuf(f,textpuffer);
try
bytesloaded := 0;
capacity := tsr.size div 60;
if capacity < 128 then capacity := 128;
while not eof(f)
do begin
if count >= capacity then
begin
actlinelen := bytesloaded div count;
capacity := (count+ ((tsr.size-bytesloaded) div actlinelen))+8
end;
setlength(s,128);
blockread(f,s[1],128,dummy);
bytesloaded := bytesloaded+length(s)+2; //fr Enter
addstring(s);
end;
finally
s.free;
findclose(tsr);
system.close(f);
end;
end;
Is the memory leakage observed with readln real or only
a misinterpretation of the getheapstatus values?
If it is real, how can I avoid it (execpt using tStringlist,
which worked very bad, or writing a blockread or stream
based routine which will be far more complicated than
readln)?
Thank you in advance for any hint,
Volker