[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