使用Delphi进行内存泄漏

时间:2014-01-20 10:19:27

标签: delphi memory-leaks delphi-xe

我有这个程序:

procedure TMainForm.ExtractActor(const actor_id : string);
var
  mystream : TStringStream;
  js : TlkJSONobject;
begin
    mystream:= TStringStream.Create('');
    idHTTP1.Get(TIdURI.URLEncode('some dynamic url'),mystream);                                               
    js := TlkJSON.ParseText( mystream.DataString ) as TlkJsonObject;
    //insert
    if UniConnection1.Connected then
    begin
      UniQuery3.Params[0].Value:= StrToInt(js.getString('id'));
      UniQuery3.Open;
      if (UniQuery3.RecordCount = 0) then
      begin
        Uniquery2.Params[0].Value:= StrToInt(js.getString('id'));
        Uniquery2.Params[1].Text:= js.getString('name');
        Uniquery2.Params[2].Text:= js.getString('locale');
        Uniquery2.Params[3].Text:= js.getString('gender');
        Uniquery2.Params[4].Text:= js.getString('username');
        Uniquery2.Execute;
      end;
      UniQuery3.Close;
    end;
    mystream.Free;
end;

监控Windows任务管理器我发现进程内存不断增加。大约一天后,我将收到Out of Memory错误,应用程序将崩溃。我究竟做错了什么?我假设JSON或Devart UniDAC库都没有泄漏。

1 个答案:

答案 0 :(得分:6)

有几个明显的泄漏原因。

肯定是泄漏的是您创建的js对象,但无法销毁。使用try / finally块保护其生命周期:

js := TlkJSON.ParseText( mystream.DataString ) as TlkJsonObject;
try
  ...
finally
  js.Free;
end;

更加微妙的是未受保护的mystream。如果在分配mystream之后引发异常,并且在销毁之前,您将泄漏该对象。您应该再次使用try / finally块来保护它,使用与上面演示的完全相同的习语。如果您的函数引发异常,mystream的问题只会给您带来问题。虽然这可能不是这种情况,但您必须始终以上述方式保护对象。

无论如何,您当然应该在程序中进行一些泄漏跟踪。可能会有更多的泄漏。以下是您需要采取的第一步:

  1. 更改您的代码,使其使用完整版的FastMM。
  2. 设置FastMM配置文件以进行完全调试。这可能涉及编辑.inc文件,如果您觉得太令人生畏,可以从这里使用GUI实用程序:http://jed-software.com/blog/?p=606
  3. 运行程序一段时间然后关闭它。如果您有泄漏,此时应报告这些。
  4. 修复所有泄漏。
  5. 在程序运行期间可能存在泄漏,但程序关闭时会全部整理。这些更难以跟踪,需要一些额外的程序检测。