[fpc-pascal] TIniFile crash/memory loss
Bart
bartjunk64 at gmail.com
Thu Mar 31 16:10:39 CEST 2011
When you use TIniFile with CacheUpdates := true, then when you free
the TIniFile an error can occur if the component was unable to update
the changes (in UpdateFile), this will then raise an exception, which
in turn will lead to not calling inherited Destroy, thus leading to
memory loss, which cannot be prevented anymore in this case.
Consider the following program:
program test;
{$mode objfpc}{$H+}
uses sysutils, inifiles;
program test;
{$mode objfpc}{$H+}
{$R+}
uses sysutils, inifiles;
VAR
Ini: TIniFile;
const
InvalidFilename = '/nonexisting/<|>';
BEGIN
try//try..finally
try//try..ecxcept
Ini := Nil;
Ini := tIniFile.Create(InvalidFileName);
Ini.CacheUpdates := True;
Ini.WriteString('Test','Item1','Value1');
if ParamCount > 0 then Ini.UpdateFile;
except
writeln('Exception handled');
end;
finally
if Assigned(Ini) then
begin
try
Ini.Free;
except
writeln('Exception during free');
end;
end;
end;
END.
bart at simenon:~/LazarusProjecten/ConsoleProjecten> fpc -gh test.pp
Free Pascal Compiler version 2.4.2 [2010/11/08] for i386
Copyright (c) 1993-2010 by Florian Klaempfl
Target OS: Linux for i386
Compiling test.pp
Linking test
32 lines compiled, 0.9 sec
bart at simenon:~/LazarusProjecten/ConsoleProjecten> ./test
Exception during free
Heap dump by heaptrc unit
51 memory blocks allocated : 2022/2176
42 memory blocks freed : 1896/2040
9 unfreed memory blocks : 126
True heap size : 425984
True free heap : 425152
Should be : 425272
[..snipped..]
bart at simenon:~/LazarusProjecten/ConsoleProjecten> ./test 1
Exception handled
Exception during free
Heap dump by heaptrc unit
70 memory blocks allocated : 2494/2728
61 memory blocks freed : 2368/2592
9 unfreed memory blocks : 126
True heap size : 425984
True free heap : 425152
Should be : 425272
[..snipped..]
Should I report this behaviour as a bug, or is it considered "by design"?
(My old Delphi does not support the CacheUpdates property, so I cannot
test how it behaves in Delphi)
The memory loss (and the raising of the exception) could be prevented lik this:
destructor TIniFile.destroy;
begin
If FDirty and FCacheUpdates then
begin
try
UpdateFile;
except
//just eat the exception
end;
end;
inherited destroy;
end;
Alternatively in UpdateFile the calls to SaveToFile/SaveToSream could
be placed inside a try..except block.
Bart
More information about the fpc-pascal
mailing list