I think this procedure does not use created TFileStream instance obviously
lazarus\fpc\3.2.2\source\packages\fcl-xml\src\xmlconf.pp line 161
procedure TXMLConfig.LoadFromFile(const AFileName: string);
Var
F : TFileStream;
begin
F:=TFileStream.Create(AFileName,fmOpenread or fmShareDenyWrite);
try
FFileName := '';
ReadXMLFile(Doc, AFilename);
FFileName:=AFileName;
finally
F.Free;
end;
end;
I think it calls ReadXMLFile of this overloaded version (xmlread.pp line 410) :
procedure ReadXMLFile(out ADoc: TXMLDocument; const AFilename: String);
var
FileStream: TStream;
begin
ADoc := nil;
FileStream := TFileStream.Create(AFilename, fmOpenRead+fmShareDenyWrite);
try
ReadXMLFile(ADoc, FileStream, FilenameToURI(AFilename));
finally
FileStream.Free;
end;
end;
procedure ReadXMLFile(out ADoc: TXMLDocument; f: TStream; const ABaseURI: String);
var
Reader: TXMLTextReader;
ldr: TLoader;
begin
ADoc := TXMLDocument.Create;
Reader := TXMLTextReader.Create(f, ABaseURI, ADoc.Names);
try
ldr.ProcessXML(ADoc, Reader);
finally
Reader.Free;
end;
end;
I think, it causes memory leak since out ADoc parameter overwrites old value of TXMLConfig's Doc.
Is FreeAndNil(Doc) call missing before first ReadXMLFile call (like in TXMLConfig.DoSetFileName) ?
To reproduce, compile with heaptrc this below :
var
FXMLConfig :TXMLConfig;
begin
FXMLConfig:= TXMLConfig.Create(nil);
FXMLConfig.LoadFromFile(FConfigFileName);
FXMLConfig.Free;
end;
To achieve issue, I use this below :
var
FXMLConfig :TXMLConfig;
begin
FXMLConfig:= TXMLConfig.Create(nil);
FXMLConfig.ReadOnly:= true;
FXMLConfig.Filename:= FConfigFileName;
FXMLConfig.Free;
end;
Probably, this may also works below:
var
FXMLConfig :TXMLConfig;
begin
FXMLConfig:= TXMLConfig.Create(nil);
FXMLConfig.Filename:= '';
FXMLConfig.FileName:= FConfigFileName;
FXMLConfig.Free;
end;
Ömür Ölmez.