I created a simple client / server DataSnap application with a wizard in Delphi XE8, using echo stream selection and reverse methods. When I put "ReportMemoryLeaksOnShutdown: = True" in the dpr server and calling the echo and / or reverse methods from the client, the result is good, but when I close the server application (after closing the client), I always get 2 or more unknown memory leaks. Is this a known bug that I cannot find on the Internet or is there a solution?
Server Code:
unit ServerMethodsUnit; interface uses System.SysUtils, System.Classes, System.Json, Datasnap.DSServer, Datasnap.DSAuth, DataSnap.DSProviderDataModuleAdapter; type {$METHODINFO ON} TServerMethods = class(TDataModule) private { Private declarations } public { Public declarations } function EchoString(Value: string): string; function ReverseString(Value: string): string; end; {$METHODINFO OFF} implementation {%CLASSGROUP 'FMX.Controls.TControl'} {$R *.dfm} uses System.StrUtils; function TServerMethods.EchoString(Value: string): string; begin Result := Value; end; function TServerMethods.ReverseString(Value: string): string; begin Result := System.StrUtils.ReverseString(Value); end; end.
Dfm
object ServerContainer: TServerContainer OldCreateOrder = False Height = 271 Width = 415 object DSServer1: TDSServer Left = 96 Top = 11 end object DSTCPServerTransport1: TDSTCPServerTransport Server = DSServer1 Filters = <> Left = 96 Top = 73 end object DSServerClass1: TDSServerClass OnGetClass = DSServerClass1GetClass Server = DSServer1 Left = 200 Top = 11 end end
Dfm project file
program DataSnap_Server; uses FMX.Forms, Web.WebReq, IdHTTPWebBrokerBridge, ServerMainForm in 'ServerMainForm.pas' {Form2}, ServerMethodsUnit in 'ServerMethodsUnit.pas' {ServerMethods: TDataModule}, ServerContainerUnit in 'ServerContainerUnit.pas' {ServerContainer: TDataModule}; {$R *.res} begin ReportMemoryLeaksOnShutdown := True; Application.Initialize; Application.CreateForm(TForm2, Form2); Application.CreateForm(TServerContainer, ServerContainer); Application.Run; end.
client code generated source code
// // Created by the DataSnap proxy generator. // 14-5-2015 22:45:56 // unit ClientClassesUnit; interface uses System.JSON, Data.DBXCommon, Data.DBXClient, Data.DBXDataSnap, Data.DBXJSON, Datasnap.DSProxy, System.Classes, System.SysUtils, Data.DB, Data.SqlExpr, Data.DBXDBReaders, Data.DBXCDSReaders, Data.DBXJSONReflect; type TServerMethodsClient = class(TDSAdminClient) private FEchoStringCommand: TDBXCommand; FReverseStringCommand: TDBXCommand; public constructor Create(ADBXConnection: TDBXConnection); overload; constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload; destructor Destroy; override; function EchoString(Value: string): string; function ReverseString(Value: string): string; end; implementation function TServerMethodsClient.EchoString(Value: string): string; begin if FEchoStringCommand = nil then begin FEchoStringCommand := FDBXConnection.CreateCommand; FEchoStringCommand.CommandType := TDBXCommandTypes.DSServerMethod; FEchoStringCommand.Text := 'TServerMethods.EchoString'; FEchoStringCommand.Prepare; end; FEchoStringCommand.Parameters[0].Value.SetWideString(Value); FEchoStringCommand.ExecuteUpdate; Result := FEchoStringCommand.Parameters[1].Value.GetWideString; end; function TServerMethodsClient.ReverseString(Value: string): string; begin if FReverseStringCommand = nil then begin FReverseStringCommand := FDBXConnection.CreateCommand; FReverseStringCommand.CommandType := TDBXCommandTypes.DSServerMethod; FReverseStringCommand.Text := 'TServerMethods.ReverseString'; FReverseStringCommand.Prepare; end; FReverseStringCommand.Parameters[0].Value.SetWideString(Value); FReverseStringCommand.ExecuteUpdate; Result := FReverseStringCommand.Parameters[1].Value.GetWideString; end; constructor TServerMethodsClient.Create(ADBXConnection: TDBXConnection); begin inherited Create(ADBXConnection); end; constructor TServerMethodsClient.Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); begin inherited Create(ADBXConnection, AInstanceOwner); end; destructor TServerMethodsClient.Destroy; begin FEchoStringCommand.DisposeOf; FReverseStringCommand.DisposeOf; inherited; end; end.
Own source
unit ClientMainForm; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Button2: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses ClientModuleUnit; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption := ClientModule.ServerMethodsClient.EchoString(Edit1.Text); end; procedure TForm1.Button2Click(Sender: TObject); begin Label1.Caption := ClientModule.ServerMethodsClient.ReverseString(Edit1.Text); end; end.