当我尝试免费的 TJSONObject 时出现访问冲突
Access violation when i try free TJSONObject
我有下面的代码,但是当我尝试释放变量 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 客户端模块向导创建了我的 class TcmClientModule。
也许你在做这件事的时候
clientModule.DisposeOf;
checkID
会被销毁,因为checkID
是clientModule
的一部分,由于这部分代码
clientModule.smMethodsServerClient.CheckID(AID);
您可以尝试先清除 checkID
,然后再清除 clientModule
。
更新:另一种避免错误的方法是在销毁前检查checkId
。
也许这样适合:
if Assigned(checkId) then
checkID.Free;
也许除了这个检查你还需要 null
检查对象。
作为DataSnap参数的JSONValue不需要是Free
另外,如果释放了参数对象的内存,在释放DataSnap DataModule或者第二次调用该参数所在的接口时,可能会出错
即使每次使用DataSnap接口都新建一个JSONValue参数,也不存在内存泄露等问题
此外,不应进一步释放通过 DataSnap 接口接收的 JSONValue 对象。
============================================= ====
clientModule.DisposeOf;
这会为 checkID 释放内存。但是,没有“checkID := nil”的设置。下面的条件语句会一直执行,执行时出错
if Assigned(checkId) then
checkID.Free;
我有下面的代码,但是当我尝试释放变量 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 客户端模块向导创建了我的 class TcmClientModule。
也许你在做这件事的时候
clientModule.DisposeOf;
checkID
会被销毁,因为checkID
是clientModule
的一部分,由于这部分代码
clientModule.smMethodsServerClient.CheckID(AID);
您可以尝试先清除 checkID
,然后再清除 clientModule
。
更新:另一种避免错误的方法是在销毁前检查checkId
。
也许这样适合:
if Assigned(checkId) then
checkID.Free;
也许除了这个检查你还需要 null
检查对象。
作为DataSnap参数的JSONValue不需要是Free
另外,如果释放了参数对象的内存,在释放DataSnap DataModule或者第二次调用该参数所在的接口时,可能会出错
即使每次使用DataSnap接口都新建一个JSONValue参数,也不存在内存泄露等问题
此外,不应进一步释放通过 DataSnap 接口接收的 JSONValue 对象。
============================================= ====
clientModule.DisposeOf;
这会为 checkID 释放内存。但是,没有“checkID := nil”的设置。下面的条件语句会一直执行,执行时出错
if Assigned(checkId) then
checkID.Free;