gpt4 book ai didi

Delphi XE8 简单 DataSnap 客户端和服务器应用程序中的未知内存泄漏

转载 作者:行者123 更新时间:2023-12-03 15:02:37 24 4
gpt4 key购买 nike

我使用 echostring 和 reversestring 示例方法,通过 Delphi XE8 中的向导创建了一个简单的 DataSnap 客户端/服务器应用程序。当我将“ReportMemoryLeaksOnShutdown := True”放入服务器 dpr 并从客户端调用 echostring 和/或反向字符串方法时,结果很好,但是当我关闭服务器应用程序(关闭客户端后)时,我总是得到 2 个或更多未知内存泄漏。这是我在互联网上找不到的已知错误还是有解决方案?

服务器代码:

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项目文件

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.

客户端代码生成源

// 
// 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.

自己的来源

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.

最佳答案

内存泄漏看起来总是存在,或者,我们做错了什么。

我检查的内容:

我将所有服务器应用程序代码移至一个单元中。我尝试不使用 FMX 的服务器应用程序 - 使用 VCL。我尝试在运行时与父级 Self 和 Nil 创建 TDSServer、TDSTCPServerTransport、TDSServerClass。我尝试使用 TServerMethod 类所有者 TPersistance 和 TComponent (Delphi 帮助说要使用它)。我尝试在 Delphi XE7 Update 1 和 Delphi XE8 中将编译的服务器应用程序作为 32 位和 64 位应用程序。

EurekaLog 7.2.2 也无法捕获有关内存泄漏的详细信息。为了避免 EurekaLog 捕获访问冲突,需要在退出前使用 DSServer1.Stop。

我们可以看到当您使用 EurekaLog 时发生访问冲突基本上是在System.TObject.InheritsFrom(???)System._IsClass($64AE4E0,TDSServerTransport)Datasnap.DSCommonServer.TDSCustomServer.StopTransportsDatasnap.DSCommonServer.TDSCustomServer.StopDatasnap.DSServer.TDSServer.StopDatasnap.DSServer.TDSServer.Destroy系统.TObject.FreeSystem.Classes.TComponent.DestroyComponentsSystem.Classes.TComponent.DestroySystem.Classes.TDataModule.Destroy系统.TObject.FreeSystem.Classes.TComponent.DestroyComponentsFMX.Forms.DoneApplication系统.SysUtils.DoExitProc系统._Halt0:00408da8 TObject.InheritsFrom + $8

服务器应用程序:

unit ufmMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Datasnap.DSServer, Datasnap.DSTCPServerTransport, Datasnap.DSAuth, DataSnap.DSProviderDataModuleAdapter, Datasnap.DSCommonServer,
IPPeerServer;

type
{$METHODINFO ON}
TServerMethods = class(TComponent)
private
{ Private declarations }
public
{ Public declarations }
function EchoString(Value: string): string;
end;
{$METHODINFO OFF}


TfmMain = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
DSServer1: TDSServer;
DSTCPServerTransport1: TDSTCPServerTransport;
DSServerClass1: TDSServerClass;
procedure DSServerClass1GetClass(DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
end;

var
fmMain: TfmMain;

implementation

{$R *.dfm}

uses System.StrUtils;

function TServerMethods.EchoString(Value: string): string;
begin
Result := Value;
end;

procedure TfmMain.DSServerClass1GetClass(DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
PersistentClass := TServerMethods;
end;

procedure TfmMain.FormCreate(Sender: TObject);
begin
DSServer1 := TDSServer.Create(nil);
DSServer1.Name := 'DSServer1';
DSServer1.AutoStart := False;

DSTCPServerTransport1 := TDSTCPServerTransport.Create(nil);
DSTCPServerTransport1.Server := DSServer1;

DSServerClass1 := TDSServerClass.Create(nil);
DSServerClass1.Server := DSServer1;
DSServerClass1.OnGetClass := DSServerClass1GetClass;

DSServer1.Start;
end;

procedure TfmMain.FormDestroy(Sender: TObject);
begin
DSServer1.Stop;

DSServerClass1.Free;
DSTCPServerTransport1.Free;
DSServer1.Free;
end;

end.

关于Delphi XE8 简单 DataSnap 客户端和服务器应用程序中的未知内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30247812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com