2016-12-04 21 views
2

私は基本的なDataSnapサーバを使用しています。 私はXE8を使用しています、窓8.1TStreamとメモリリークを返すDelphiのDataSnap関数

私は次のサーバ機能を持っている:

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

ストリームを解放するかどうか、およびストリームを解放するタイミングをサーバーがどのように知っていますか? – MartynA

+0

@MartynAこれは、起動ライフサイクルを持つDataSnapサーバーです。あなたはまた私が知りたいことを尋ねます。 –

+0

申し訳ありませんが、私のqは少し修辞的でした。どのようにしてサーバがルーチン内のヒープ割り当てを "知っている"ことができるのでしょうか? – MartynA

答えて

4

私はこれを調べるための実験を行い、その結果は私を驚かせました。

ましょうDataSnapServerウィザード(ファイルの下で|新規|その他| Delphiプロジェクト| DataSnapサーバー)デフォルトのサーバープロジェクトを作成し、以下の追加

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にブレークポイントを置きます TMyStringStream.Destroyと実行します。

次に、/作成するには、クライアントでボタン2をクリックすると、この

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でブレークポイントで停止したことがわかります。これはDataSnap.DSReflectでfunction TDSMethodValues.ClearReferenceParameters: boolean

if not FServerSideCommand then 
    try 
     FreeAndNil(FAllocatedReturn) 
    except 
     Result := false 
    end; 

ブロックで実行FreeAndNil(FAllocatedReturn) の結果です。

したがって、サーバーメソッドで割り当てられ、 に割り当てられているストリームのように見えます。その結果は解放されます(あなたが気に入っているかどうかにかかわらず)ので、漏れません。しかし、私はあなたが一般的なルールの狭い例外として、ローカル変数を介してDelphiオブジェクトを作成する場合、変数がスコープから外れる前にそれを処分する必要があるとみなすべきだと思います。

+0

だから、これはあなたのqに答えましたか? – MartynA

+0

はい、ありがとうございます。あなたは良い仕事をしました。 –

関連する問題