'Reason why a freed TStringList counts as memory leak in the FastMM4 report

After noticing an odd memory behavior in task manager in one of my applications I started investigating memory leaks with FastMM4. I found more than 1000 just after opening three forms. I hope I will be able to find the cause in a single place

In one case, even if always free the TStringList in the finally block (that is always reached), FastMM4 reports a memory leak:

function GetMatchingResourceFileName(MatchingString:string) : string;
var
  ResourcesList: TStringList;
  I : Integer;
begin
  Result := '';
  try
    ResourcesList := TStringList.Create;
    // get resource files list
    ResourcesList := GetResourceList;
    //search for matching file name
    for I := 0 to ResourcesList.Count-1 do
    begin
      if Pos(MatchingString,ResourcesList.Strings[I]) > 0 then
      begin
        Result := ResourcesList.Strings[I];
        break;
      end;
    end;
  finally
    ResourcesList.Free;
    ResourcesList:= nil;
  end;
end;

FastMM4 stack report tells me that the leak starts from

ResourcesList := TStringList.Create;

even if I am 100% sure that ResourcesList.Free; is executed I see the memory leak.

Here you can see that the breakpoint is hit: breakpoint being hit

As I close the app I see the report:

---------------------------
myProject.exe: Memory Leak Detected
---------------------------
This application has leaked memory. The small-block leaks are (excluding expected leaks registered by pointer):



85 - 100 bytes: System.Classes.TStringList x 1



Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".

To study the leak above I commented 99% of my code focus on the first reported leak, in fact, one in the initialization part of the app.

How this is possible?

Update

The working version of the code avoids to call TStringList.Create since the GetResourceList method already returns a properly created TStringList, the following code is now leak free:

function GetMatchingResourceFileName(MatchingString:string) : string;
var
  ResourcesList: TStringList;
  I : Integer;
begin
  Result := '';
  try
    ResourcesList := GetResourceList;
    //search for matching file name
    for I := 0 to ResourcesList.Count-1 do
[...]


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source