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

时间:2016-12-04 03:16:21

标签: delphi memory-leaks datasnap

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

我有下一个服务器功能:

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

我的客户端应用是Android应用。一切运作良好,我可以得到结论。

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

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

1 个答案:

答案 0 :(得分:4)

我做了一个实验来研究这个,结果让我感到惊讶。

让DataSnapServer向导(在File | New | Other | Delphi Projects |。下) 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;

,编译,在Clear的{​​{1}}上放置一个断点并运行。

然后,创建/运行一个像这样做

的最小客户端
TMyStringStream.Destroy

如果您随后在客户端中单击Button2,您将发现服务器已停止 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; 中的断点。这是TMyStringStream.Destroy的结果 在块中执行

FreeAndNil(FAllocatedReturn)

在DataSnap.DSReflect中的 if not FServerSideCommand then try FreeAndNil(FAllocatedReturn) except Result := false end;

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