#1 2014-06-21 20:24:56

avista
Member
Registered: 2014-01-06
Posts: 63

Memory Leak in Interface Based Service Declaration

I suspect this is related to the new automatic RTTI initialization of records for serialization.

Using the 'Project14ServerHttp' demo, the following declaration in the interface will cause a memory leak:

/// some common definitions shared by both client and server side 
unit Project14Interface;

interface

type
  TTestRec = packed record
    Value1: Integer;
    Value2: Integer;
  end;

  ICalculator = interface(IInvokable)
    ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
    function Add(n1,n2: integer): integer;
    function GetTestRec(Id: integer; out aRec: TTestRec): Boolean; <-----------------------
  end;

const
  ROOT_NAME = 'root';
  PORT_NAME = '888';
  APPLICATION_NAME = 'RestService';

implementation

end.
/// this server will use TSQLRestServerFullMemory over HTTP
program Project14ServerHttp;

{$APPTYPE CONSOLE}

uses
  FastMM4,
  SysUtils,
  Classes,
  SynCommons,
  mORMot,
  mORMotHttpServer,
  Project14Interface;

type
  TServiceCalculator = class(TInterfacedObjectWithCustomCreate, ICalculator)
  public
    function Add(n1,n2: integer): integer;
    function GetTestRec(Id: integer; out aRec: TTestRec): Boolean;
  end;

function TServiceCalculator.Add(n1, n2: integer): integer;
begin
  result := n1+n2;
end;

function TServiceCalculator.GetTestRec(Id: integer; out aRec: TTestRec): Boolean;
begin
  aRec.Value1 := 1;
  aRec.Value2 := 2;
  Result := True;
end;

[...]
begin
  ReportMemoryLeaksOnShutdown := True; <-----------------------
  [...]
end.

You just need to run it, and then press the Enter key.

Offline

#2 2014-06-22 07:51:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Memory Leak in Interface Based Service Declaration

We have just fixed several memory leaks under newer versions of Delphi.
Main issue was linked to enhanced RTTI, as you discovered.

And there was also some problems due to newer compiler issues, like unproper method inlining or old object type regression.
Now all regression tests pass, without any memory leak reported.

See http://synopse.info/fossil/info/2ccd2e0b6f

Thanks a lot for the feedback, and to have supplied a simple program to reproduce the issue.
It is so much easier to investigate when you got something to work clear on!
smile

Offline

#3 2014-06-22 20:17:15

avista
Member
Registered: 2014-01-06
Posts: 63

Re: Memory Leak in Interface Based Service Declaration

Glad my example helped. smile

I've encountered another case, where the memory manager reports a leak.

If you reference a threadvar in the code, before raising an exception, a leak occurs:

threadvar            <---------------------------------
  aString: string;   <---------------------------------

function TServiceCalculator.Add(n1, n2: integer): integer;
begin
  result := n1+n2;
end;

function TServiceCalculator.GetTestRec(Id: integer; out aRec: TTestRec): Boolean;
begin
  aRec.Value1 := 1;
  aRec.Value2 := 2;
  aRec.Value3 := 'test';
  aString := 'test'; <---------------------------------
  raise Exception.Create('Error Message');
  Result := True;
end;

It's an unusual case, but we encountered it because one of our threads did something similar.

Last edited by avista (2014-06-22 20:19:22)

Offline

#4 2014-06-22 21:10:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Memory Leak in Interface Based Service Declaration

This is not linked to mORMot, but to threadvar itself.

You should not use a managed type within a threadvar, otherwise a memory leak may occur.
See http://www.delphibasics.co.uk/RTL.asp?Name=ThreadVar
and http://stackoverflow.com/q/5456317/458259

My advice is to never use a string in a threadvar, but non managed values (like integer/cardinal) or pointers/objects to some data which will have their live time managed by other piece of code.

Offline

#5 2014-06-22 21:15:18

avista
Member
Registered: 2014-01-06
Posts: 63

Re: Memory Leak in Interface Based Service Declaration

Thanks, we will change the code to avoid this.

Offline

Board footer

Powered by FluxBB