使用Delphi实现内存泄漏

使用Delphi实现内存泄漏,delphi,memory-leaks,delphi-xe,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);

我有以下程序:

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任务管理器我看到进程内存不断增加。大约一天后,我会出现内存不足错误,应用程序将崩溃。我做错了什么?我假设JSON或Devart UniDAC库都没有泄漏。

有几个明显的泄漏原因

肯定是泄漏的是您创建但未能销毁的
js
对象。使用
try
/
最后
块保护其生存期:

js := TlkJSON.ParseText( mystream.DataString ) as TlkJsonObject;
try
  ...
finally
  js.Free;
end;
更微妙的是未受保护的
mystream
。如果在分配了
mystream
之后以及在销毁之前引发异常,您将泄漏该对象。同样,您应该使用与上面演示的完全相同的习惯用法,使用
try
/
finally
块来保护它。只有在您的函数引发异常时,
mystream
的问题才会成为您的问题。虽然这里可能不是这样,但您必须始终以上述方式保护对象

在任何情况下,您都应该在程序中进行一些泄漏跟踪。很可能会有更多的泄漏。以下是您需要采取的第一步:

  • 更改代码,使其使用完整版本的FastMM
  • 为完全调试设置FastMM配置文件。这可能涉及编辑.inc文件,如果您觉得这太令人望而生畏,您可以从这里使用GUI实用程序:
  • 运行程序一段时间,然后关闭它。如果有泄漏,应在此时报告
  • 修复所有的漏洞

  • 在程序运行过程中可能存在漏洞,但当程序关闭时,这些漏洞都会被清理干净。这些很难跟踪,并且需要对程序进行一些额外的检测。

    导致泄漏的原因有两个

    肯定是泄漏的是您创建但未能销毁的
    js
    对象。使用
    try
    /
    最后
    块保护其生存期:

    js := TlkJSON.ParseText( mystream.DataString ) as TlkJsonObject;
    try
      ...
    finally
      js.Free;
    end;
    
    更微妙的是未受保护的
    mystream
    。如果在分配了
    mystream
    之后以及在销毁之前引发异常,您将泄漏该对象。同样,您应该使用与上面演示的完全相同的习惯用法,使用
    try
    /
    finally
    块来保护它。只有在您的函数引发异常时,
    mystream
    的问题才会成为您的问题。虽然这里可能不是这样,但您必须始终以上述方式保护对象

    在任何情况下,您都应该在程序中进行一些泄漏跟踪。很可能会有更多的泄漏。以下是您需要采取的第一步:

  • 更改代码,使其使用完整版本的FastMM
  • 为完全调试设置FastMM配置文件。这可能涉及编辑.inc文件,如果您觉得这太令人望而生畏,您可以从这里使用GUI实用程序:
  • 运行程序一段时间,然后关闭它。如果有泄漏,应在此时报告
  • 修复所有的漏洞

  • 在程序运行过程中可能存在漏洞,但当程序关闭时,这些漏洞都会被清理干净。这些问题更难跟踪,需要对您的程序进行一些额外的检测。

    谢谢。但是,如果在没有try块的情况下发生异常,它将使应用程序崩溃,并且是可见的。它至少可以运行一天。最后它会停止,我会在关闭它后收到“内存不足”的消息框。@MiguelE阅读关于
    js
    的部分。此外,请不要只是修复,然后忘记所有的泄漏。添加FastMM完全调试并修复它们。泄漏就像口袋妖怪一样。@MiguelE“但是如果在没有try块的情况下发生异常,它将使应用程序崩溃,并且它将是可见的。”。。。除非您做了一些具体的事情导致应用程序崩溃,否则这不是真的。默认异常处理时,当前操作将停止,用户将看到错误消息;应用程序将继续运行。事实上,如果异常是
    EAbort
    类,用户甚至看不到错误消息。@此外,您也不想在该方法之外的代码中浪费时间,担心它是否与该方法未实现适当资源保护的事实兼容。就这么做吧——没有理由不这么做!谢谢但是,如果在没有try块的情况下发生异常,它将使应用程序崩溃,并且是可见的。它至少可以运行一天。最后它会停止,我会在关闭它后收到“内存不足”的消息框。@MiguelE阅读关于
    js
    的部分。此外,请不要只是修复,然后忘记所有的泄漏。添加FastMM完全调试并修复它们。泄漏就像口袋妖怪一样。@MiguelE“但是如果在没有try块的情况下发生异常,它将使应用程序崩溃,并且它将是可见的。”。。。除非您做了一些具体的事情导致应用程序崩溃,否则这不是真的。默认异常处理时,当前操作将停止,用户将看到错误消息;应用程序将继续运行。事实上,如果异常是
    EAbort
    类,用户甚至看不到错误消息。@此外,您也不想在该方法之外的代码中浪费时间,担心它是否与该方法未实现适当资源保护的事实兼容。就这么做吧——没有理由不这么做!