<div dir="ltr">Hello,<div><br></div><div>I've used the useful singletons available in the TEncoding class, and I don't get any problem with them, unless using threads.</div><div><br></div><div>I have an application that does many tests in a code compilable in FPC and Delphi, however, the FPC's tests raise memory leak at the finalization tests. The problem can be a little bit hard to be reproduce, but I think the code below can do that:</div><div><br></div><div>=== begin code [project1.dpr] ===</div><div><br></div><div><div>program project1;</div><div><br></div><div>{$IFDEF FPC}</div><div>{$MODE DELPHI}</div><div>{$ENDIF}</div><div>{$IFDEF MSWINDOWS}</div><div>{$APPTYPE CONSOLE}</div><div>{$ENDIF}</div><div><br></div><div>uses</div><div>//  HeapTrc, the FPC staff recomends to enable HeapTrc in the lpi or passing the -gh compiler parameter</div><div>{$IFDEF UNIX}</div><div>  CThreads,</div><div>{$ENDIF} SysUtils, Classes;</div><div><br></div><div>type</div><div>  TTestThread = class(TThread)</div><div>  public</div><div>    constructor Create;</div><div>    procedure Execute; override;</div><div>  end;</div><div><br></div><div>  constructor TTestThread.Create;</div><div>  begin</div><div>    inherited Create(True);</div><div>    FreeOnTerminate := False;</div><div>  end;</div><div><br></div><div>  procedure TTestThread.Execute;</div><div>  begin</div><div>    WriteLn(TEncoding.Default.GetString(TBytes.Create(65, 66, 67)));</div><div>  end;</div><div><br></div><div>var</div><div>  VThread1, VThread2: TTestThread;</div><div>begin</div><div>{$IFNDEF FPC}</div><div>  ReportMemoryLeaksOnShutdown := True;</div><div>{$ENDIF}</div><div>  VThread1 := TTestThread.Create;</div><div>  VThread2 := TTestThread.Create;</div><div>  try</div><div>    Sleep(1000);</div><div>    VThread1.Start;</div><div>    VThread2.Start;</div><div>    VThread1.WaitFor;</div><div>    VThread2.WaitFor;</div><div>  finally</div><div>    VThread1.Free;</div><div>    VThread2.Free;</div><div>  end;</div><div>end.</div></div><div><br></div><div>=== end code ===</div><div><br></div><div>If you compile and run the code above, you may get the following trace:</div><div><br></div><div>=== begin log ===</div><div><br></div><div><div>ABC</div><div>ABC</div><div>Heap dump by heaptrc unit</div><div>44 memory blocks allocated : 2119/2144</div><div>43 memory blocks freed     : 2087/2112</div><div>1 unfreed memory blocks : 32</div><div>True heap size : 131072</div><div>True free heap : 131072</div><div>Should be : 130912</div><div>Call trace for block $00007FFFF7FAB0C0 size 32</div></div><div><br></div><div>=== end log ===<br clear="all"><div><br></div><div>Researching the FPC's TEncoding implementation, I think it doesn't do any lock before instantiate its singletons, so I decided to research how Delphi implements it, because I can't get any error on it, and I've seen it implements a <a href="http://stackoverflow.com/a/24657705/3268398">"lock-free initialization" technique</a> using the XE's AtomicCmpExchange() function before return any TEncoding global instance.</div><div><br></div><div>That memory leak can be really a problem, because I can't prevent how many threads will call the TEncoding's singletons at same time, I could initialize the TEncoding before starting any thread of my application, but it doesn't sound good, because I can't prevent if the threads will instantiate the ANSI or UTF8 singleton. The best way to solve this problem would be making the TEncoding become thread-safe. I could send a patch to solve it, but I don't know if FPC provides some global locker like AtomicCmpExchange.</div><div><br></div>--<br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div>Silvio Clécio</div></div></div>
</div></div>