Delphi DataSnap函数返回TStream和内存泄漏

Lui*_*ves 2 delphi memory-leaks datasnap

我正在使用基本的 DataSnap 服务器。\n我正在使用 XE8、Windows 8.1

\n\n

我有下一个服务器功能:

\n\n
function TSrvServerMetodos.ImagePac(pront:integer): TStream;\nvar blob:TStream;\n    strm:TMemoryStream;\nbegin\n  with qrytemp do begin\n        Params.Clear;\n        SQL.Clear;\n        SQL.Add('SELECT F.PICTURE FROM CLIENTES F WHERE F.PRONT=:pront');\n        UnPrepare;\n        Prepare;\n        Params[0].Value:=pront;\n        Open;\n        if IsEmpty then result:=nil\n        else begin\n         try\n              Result := CreateBlobStream(fieldbyname('pict'),bmRead);\n              GetInvocationMetadata.ResponseContentType := 'image/jpeg';\n         except\n              Result:=nil\n         end;\n        end;\n  end;\nend;\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的客户端应用程序是 Android 应用程序。一切正常,我可以获得 p\xc3\xadcture 。

\n\n

我的疑问是 Datasnap 服务器上的内存泄漏。

\n\n

由于结果是我创建的 TStream,Datasnap Server 会小心释放它,否则我会遇到内存泄漏问题?

\n

Mar*_*ynA 5

我做了一个实验来研究这个问题,结果令我惊讶。

让 DataSnapServer 向导(在文件 | 新建 | 其他 | Delphi 项目 | DataSnap Server 下)创建一个默认服务器项目,然后进行以下添加

type
  TMyStringStream = class(TStringStream)
  public
    constructor Create(Value : String);
    destructor Destroy; override;
  end;

  TServerMethods1 = class(TDSServerModule)
[...]

function TServerMethods1.GetStream(Value: String): TStream;
var
  SS : TMyStringStream;
begin
  SS := TMyStringStream.Create(Value);
  SS.Position := 0;
  Result := SS;
end;

constructor TMyStringStream.Create(Value: String);
begin
  inherited Create;
  WriteString(Value);
end;

destructor TMyStringStream.Destroy;
begin
  Clear;
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

,编译,断点,Clear运行TMyStringStream.Destroy

然后,创建/运行一个最小的客户端,它执行类似的操作

procedure TDSClientForm.Button2Click(Sender: TObject);
var
  SS : TStringStream;
  S : TStream;
begin
  SqlServerMethod2.Params[0].AsString := 'ABC123';
  SqlServerMethod2.ExecuteMethod;
  SS := TStringStream.Create;
  try
    S := SqlServerMethod2.Params[1].AsStream; //, 6{SqlServerMethod2.Params[1].Size});
    S.Position := 0;
    SS.CopyFrom(S, S.Size);
    ShowMessage(SS.DataString);
  finally
    SS.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

如果您随后在客户端中单击 Button2,您会发现服务器停在 中的断点处TMyStringStream.DestroyFreeAndNil(FAllocatedReturn) 这是在块中执行的结果

  if not FServerSideCommand then
    try
      FreeAndNil(FAllocatedReturn)
    except
      Result := false
    end;
Run Code Online (Sandbox Code Playgroud)

function TDSMethodValues.ClearReferenceParameters: booleanDataSnap.DSReflect 中。

因此,它看起来像在服务器方法中分配并分配给其 Result 的 Stream 将被释放(无论您是否喜欢),因此不会泄漏。但我认为您应该将其视为一般规则的一个狭隘例外,即如果您通过局部变量创建 Delphi 对象,则应该在变量超出范围之前将其释放。