I am using a basic DataSnap server. I am using XE8, windows 8.1
I have the next server function:
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;
My client app is an Android app. All works well and I can get the pícture .
My doubt is about memory leak on Datasnap server.
Since result is a TStream that I created, Datasnap Server will take care to free it or I will have problems with memory leak?
I did an experiment to look into this and the result surprised me.
Let the DataSnapServer Wizard (under File | New | Other | Delphi Projects | DataSnap Server) create a default server project and then make the following additions
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;
, compile, put a breakpoint on Clear
in TMyStringStream.Destroy
and run.
Then, create/run a minimal client which does something like this
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;
If you then click Button2 in the client, you'll find that the server stops on the breakpoint in TMyStringStream.Destroy
. This is a result of FreeAndNil(FAllocatedReturn)
executing in the block
if not FServerSideCommand then
try
FreeAndNil(FAllocatedReturn)
except
Result := false
end;
in function TDSMethodValues.ClearReferenceParameters: boolean
in DataSnap.DSReflect.
So it looks like a Stream which is allocated in your server method AND is assigned to its Result will be freed (whether you like it or not), so that won't leak. But I think you should regard that as a narrow exception to the general rule that if you create a Delphi object via a local variable, you should dispose of it before the variable goes out of scope.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.