复杂json对象中的TJSONObject内存泄漏
我正在尝试使用带有DelphiXe5的idHTTPserver在小型企业环境中本地提供RESTAPI服务。我在将文件发送到客户端之前对其进行了预处理,此时出现了一些问题。进程完成后,不会释放内存。复杂json对象中的TJSONObject内存泄漏,json,delphi,delphi-xe5,Json,Delphi,Delphi Xe5,我正在尝试使用带有DelphiXe5的idHTTPserver在小型企业环境中本地提供RESTAPI服务。我在将文件发送到客户端之前对其进行了预处理,此时出现了一些问题。进程完成后,不会释放内存。 创建的JSON对象最终被正确地发送到客户端(AngularJS应用程序) 我做错了什么 当我收到HTTP客户端请求时,我会这样做 Procedure TMain.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPReq
创建的JSON对象最终被正确地发送到客户端(AngularJS应用程序) 我做错了什么 当我收到HTTP客户端请求时,我会这样做
Procedure TMain.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Var
// Here Var Types
Json,LFilename:String;
ROOTCOMANDAS,TORDEN,DATA,MSG : TJSONObject;
Dlnew,d : TJSONArray
files:tfilestream;
Begin
LFilename := ARequestInfo.Document;
if AnsiSameText(LFilename, '/resto/orders/jsondata') then
begin
files := TFileStream.Create('htd' + LFilename, fmOpenRead + fmShareDenyWrite);
Json := ReadStringFromStream(files);
files.Free;
ROOTCOMANDAS := TJSONOBJECT.ParseJSONValue(TEncoding.ASCII.GetBytes(Json), 0) as TJSONOBJECT;
try
Data := ROOTCOMANDAS.Get('data').JSONValue as TJSONOBJECT;
d := Data.Get('d').JSONValue as TJSONArray;
dlnew := TJSONArray.Create;
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
dlnew.AddElement(LValue);
TORDEN := TJSONOBJECT.Create;
Msg := TJSONOBJECT.Create;
Msg.AddPair(TJSONPair.Create('t', TJSONString.Create('m5000_325')));
Msg.AddPair(TJSONPair.Create('tipo', TJSONNumber.Create(5)));
TORDEN.AddPair(TJSONPair.Create('msg', Msg));
Msg := TJSONOBJECT.Create;
Msg.AddPair(TJSONPair.Create('et', TJSONString.Create(ETAGL)));
Msg.AddPair(TJSONPair.Create('d', dlnew));
TORDEN.AddPair(TJSONPair.Create('data', Msg));
TORDEN.AddPair(TJSONPair.Create('ok', TJSONTrue.Create));
TORDEN.AddPair(TJSONPair.Create('md', TJSONNumber.Create(iFD)));
TORDEN.AddPair(TJSONPair.Create('time', TJSONString.Create(UTC)));
Json := TORDEN.ToString;
AResponseInfo.CacheControl := 'no-cache';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-Headers'] := 'Content-Type';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-methods'] := 'GET,POST,OPTIONS';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-origin'] := '*';
AResponseInfo.CharSet := 'utf-8';
AResponseInfo.Pragma := 'Public';
AResponseInfo.Server := 'Drone';
AResponseInfo.ContentText := Json;
finally
ROOTCOMANDAS.Free;
end;
exit;
end;
您永远不会释放
TORDEN
变量,因此内存泄漏,当您尝试释放它时出现的错误是由以下几行引起的:
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
dlnew.AddElement(LValue);
LValue
归d
所有,当d
被释放时将被释放,并且您正在将LValue
添加到dlnew
中,后者也将要释放它。这里存在所有权问题,因为两个对象想要拥有并释放同一个包含的对象
尝试以下更改以解决此问题:
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
begin
dlnew.AddElement(LValue);
// here you are saying that you don't want to release object when ROOTCOMANDAS is released
LValue.Owned := false;
end;
// release ROOTCOMANDAS and d along with it
ROOTCOMANDAS.Free;
// Set back owned property to true so you don't leak objects
for LVaue in dlnew do
LValue.Owned := true;
...
Json := TORDEN.ToString;
TORDEN.Free;
... remove superfluous ROOTCOMANDAS.Free; in finally part
就我所知,您并没有在任何地方释放TORDEN变量是的。。因为当我试图释放那个对象时,我得到了一个错误,当你释放ROOTCOMANDAS或者根对象时,我知道你释放了all树。。我说得对不对?为什么不展示一下你使用的变量类型?这可能会有所不同。你试过调试这个吗?完整的FastMM将告诉您泄漏了什么。你把密码删掉了直到泄露消失了吗?学习这些基本的调试技巧对每个人都有好处。你的评论没有帮助。请通过编辑问题来解决我们的问题。您已被反复要求编辑您的问题并添加所有变量声明。谢谢!!Dalija,现在好像在工作。。我不知道在DBXJSON库的TJSON对象中使用“owned”方法,非常感谢。。。哈维尔。