【发布时间】:2020-07-24 02:47:48
【问题描述】:
我有下面的代码,但是当我尝试释放变量 checkID 时,我得到一个访问冲突错误,如果我不销毁它,我会遇到内存泄漏问题。
function TdtmData.CheckID(AID: String): Boolean;
var
checkID : TJSONObject;
clientModule : TcmClientModule;
ok : Boolean;
begin
Result := False;
try
try
clientModule := TcmClientModule.Create(Self);
checkID := clientModule.smMethodsServerClient.CheckID(AID);
ok := checkID.GetValue<Boolean>('Register', False);
if not(ok) then
raise Exception.Create('ID ERROR.');
finally
clientModule.DisposeOf;
checkID.Free; // <-- The error is here (Access violation)
end;
Result := ok;
except
on e : Exception do
raise Exception.Create(e.Message);
end;
end;
smMethodsServerClient.CheckID(AID) 方法是通过 TDSRestConnection 组件自动创建的。
function TsmMethodsServerClient.CheckID(AID: string; const ARequestFilter: string): TJSONObject;
begin
if FCheckIDCommand = nil then
begin
FCheckIDCommand := FConnection.CreateCommand;
FCheckIDCommand.RequestType := 'GET';
FCheckIDCommand.Text := 'TsmMethodsServer.CheckID';
FCheckIDCommand.Prepare(TsmMethodsServer_CheckID);
end;
FCheckIDCommand.Parameters[0].Value.SetWideString(AIDPDV);
FCheckIDCommand.Execute(ARequestFilter);
Result := TJSONObject(FCheckIDCommand.Parameters[1].Value.GetJSONValue(FInstanceOwner));
end;
我还使用 Datasnap REST 客户端模块向导创建了我的类 TcmClientModule。
【问题讨论】:
-
将变量 (
checkID) 命名为与函数 (CheckID) 完全相同的名称是一个非常糟糕的主意。 Delphi 不区分大小写,旧式 Pascal 使用functionname := returnvalue而不是(现在)内置的Result从函数返回值。 -
对
TcmClientModule.Create()的调用应该在try块之上。并且应该有第二个try..finally来释放TJSONObject,假设它应该从一开始就被释放。csmMethodsServerClient.CheckID()长什么样子? -
如果 clientModule := TcmClientModule.Create(Self); 或 checkID := clientModule.smMethodsServerClient.CheckID(AID); 失败并出现异常, FINALLY 块在没有初始化 checkID 的情况下执行(参见上面 Remy 的评论),当您尝试释放未初始化的对象时,这很可能会导致访问冲突。这就是为什么您应该始终将受保护对象的分配/初始化放置在 TRY/FINALLY 块之外。
-
这是一种 DataSnap 应用程序吗?
-
这是一个datasnpat应用程序。
标签: delphi delphi-xe8 datasnap