5
votes

Using Delphi 10.2 (Tokyo)

Below is the code for a complete console app that shows an unexpected memory leak (TUTF8Encoding) when one URL is called, and no memory leak when another is called.

Comparing the headers between the two responses:

The one that leaks memory contains

 Content-Type=application/json

The one that does not leak memory contains

 Content-Type=application/json; charset=utf-8

Is this a bug, or should I be doing something to prevent this?

program RESTMemLeakTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, IPPeerClient, REST.Client, REST.Types;

var
  RESTClient1: TRESTClient;
  RESTRequest1: TRESTRequest;
  URL: string;

begin
  ReportMemoryLeaksOnShutdown := True;

  URL := 'https://httpbin.org/post'; // memory leak
  //URL := 'https://jsonplaceholder.typicode.com/posts'; // no memory leak

  RESTClient1 := TRESTClient.Create(URL);
  RESTRequest1 := TRESTRequest.Create(nil);
  try
    try
      RESTRequest1.Client := RESTClient1;
      RESTRequest1.Method := rmPOST;
      RESTRequest1.Execute;
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
  finally
    RESTRequest1.Free;
    RESTClient1.Free;
  end;
end.

Running the app with the URL that leaks memory returns this:

An unexpected memory leak has occurred. The unexpected small block leaks are:

21 - 28 bytes: TUTF8Encoding x 1

Update: Setting the FallbackCharsetEncoding to an empty string appears to "fix" the memory leak. No known issues (yet) doing this. I'm going to open a bug report with Embarcadero to see what they say. So adding the line below before the request is executed will prevent the unexpected memory leak message.

RESTClient1.FallbackCharsetEncoding := '';

Update 2: Bug report RSP-17695 was submitted on March 30, 2017.

Update 3: August 8, 2017: Bug resolved in version 10.2 Tokyo Release 1

1
This suggests that either 1) the REST client is calling TEncoding.GetEncoding(65001) or TEncoding.GetEncoding('utf-8') instead of using TEncoding.UTF8, and is not freeing the returned TEncoding (the TEncoding returned by GetEncoding() must be freed manually); 2) the REST client is using TEncoding.UTF8 and your leak report is just being generated before the global TUTF8Encoding object that backs TEncoding.UTF8 is freed during process termination. Hard to say one way or the other without seeing the call stack of the leaked memory allocation, or looking at the REST source code. - Remy Lebeau
I have the same issue in Berlin update 2 - Cesar Romero

1 Answers

2
votes

To avoid the memory leak there is a possible workaround for that:

RestClient.FallbackCharsetEncoding := '';

By setting the fallback encoding to empty or 'raw' string the "leaking" branch of the code from the REST library will be not executed and so you will not get the leak of the unreleased instance of TEncoding (which is aquired with GetEncoding()).

But this of course only wokrs if you are OK with using raw encoding fallback.

This works in Berlin Update 2. Probably can work also in later versions before the patch in Tokyo Update 1.