本人长期使用delphi,现用delphi开发了一个服务程序(使用了ADO),该程序长期在后台运行,需要经常动态创建很多对象,
用完后就释放它们,但是发现时间一长(2天),该程序占用的内存有几百兆(300M),可能是有内存泄漏(win2000 advance server),
但是我把程序移到win2000 advance server sp2,发现程序占用的内存一直在11M左右,不会增长,这令我百思不得其解。
如果Delphi好像java那样有垃圾回收机制多好,程序员可以专心的把时间放在业务逻辑上面,根本不需要考虑内存的泄漏,对象的释放问题。
以下是一个例子:
procedure TForm1.Button1Click(Sender: TObject);
var
  edit:TEdit;
  kk: TstringList;
  a: boolean;
begin
  edit:= TEdit.Create(nil);
  kk := TstringList.Create;
  //edit.Free;
  //kk.Free;
end;
用一个timer每个100ms执行一次
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Button1Click(nil);
end;
结果,程序所占的内存越来越多,把注释去掉,所占内存不会增长,这是一个明显的例子。
我使用了Boundschecker,memproof来检测漏洞,效果不理想:上面的问题没有检出来,
Boundschecker花很多时间检测系统的单元,核心单元检测不到什么问题,memproof好像没能像它所说的那样跟踪到泄漏代码的那行等等;
如果不能有效的检测并解决内存泄漏问题,那么所开发出来的长时间运行的Delphi程序都存在一个很大的隐患。这是一个很大的问题。
现请教各位高手有什么方法可以有效的解决这个问题,我用的是D6,不知是否我用的Boundschecker,memproof版本不对,请问这两个软件有for D6的吗?有的话请说明一下怎么使用,不胜感激!另外像java的垃圾回收这样好的机制,delphi应该有必要“升级”一下吧,如下一个例子delphi处理机制:
try
  对象1.create;
  对象2.create;
except
  on 异常1 do
  begin
    发生异常的业务处理1;
    对象1.free; 
  end;
  on
  on 异常2 do
  begin
    发生异常的业务处理2;
    对象2.free; 
  end;
end;  java处理机制:
try{
  new 对象1;
  new 对象2;
}  
catch
  异常1{
    发生异常的业务处理1;
  }
  异常2{
    发生异常的业务处理2;
  }
java处理让我们可以只专注于业务处理就行,但是delphi却要关心非业务方面的对象的释放问题,而且有时对象之间的释放有很大的互斥关系
如对象1未释放,就不能释放对象2等等诸如此类的问题,请各位讨论一下,帮忙up!

解决方案 »

  1.   

    Bounder有for d6的呀,按照它的说明,相应的d6的工程必须使用debug版本的lib,在d6的lib目录下有这个debug的子目录,将它加到d6的library path下,另外在工程属性框中,选中compiler页下的“Use debug DCUs”,和linker页下的“Include TD32 debug info”,(可能还有别的要求,忘了,自己看boundercheck for delphi中的说明吧),接着调试delphi6的升序时,它就可以指出相应内存泄漏所发生的程序代码了,对于类似类没有释放的错误应该是不会漏掉的!
      

  2.   

    JAVA不是编译成EXE的嘛,所以可以有垃圾回收功能。但是即使是JAVA,也不是百分百的就能回收。JAVA也有很多情况下是不能回收内存的,必须手工标记垃圾回收线程去释放。你好好看看JAVA的垃圾回收机制吧。
      

  3.   

    用java的swing开发的程序没有application server的管理,同样不需要过分关心对象的释放问题啊!
      

  4.   

    大家看看这段代码
    procedure TForm1.Button2Click(Sender: TObject);
    var
      F: file;
      Size: Integer;
      Buffer: PChar;
    begin
      AssignFile(F, 'c:\logfile.txt');
      Reset(F, 1);
      try
        Size := FileSize(F);
        GetMem(Buffer, Size);
        try
        finally
          //FreeMem(Buffer, Size);
        end;
      finally
        CloseFile(F);
      end;
    end;把FreeMem(Buffer, Size);注释掉,每按一次,程序所占内存资源就增加,但是boundchecker却没能检测出来,这是什么回事,另外,对象调用构造函数动态的创建,没有释放是属于resource leak
      

  5.   

    写代码时,就要注意这些问题,C++一样有的,这是程序员应该做的工作,不要指望第三方工具,Delphi的Try机制根本就没有问题,加一句Free,很复杂?对象没有释放是会导致内存泄漏的,这需要程序员在开发时就要考虑这个问题。Win2000自己也有这方面的问题,只要发生几率足够低就可以了
      

  6.   

    很多人也曾经抱怨 C++为什么不提供垃圾回收机制,为此C++的作者写了篇文章(我找不到了)垃圾自动回收是个双刃剑,就是效率问题。C++作者是在综合权衡利弊之后才决定放弃它的。我曾经写过一个CTI的程序,开发3个人用了3个月。维护我一个人维护了1年,开始程序从来跑不过10天,就会崩溃,我不停的找错误,找到了大约几十处内存泄漏,最后运行了50天,从8M跑到了40M。我5月份离开公司前,又找到了一个错误,现在程序已经运行了半年多,没有停过机,现在大约是16M的样子,可以说程序基本稳定了。
    这东西的确很烦,我觉得一个好的代码书写习惯会避免很多这类的错误。
      

  7.   

    我想对象创建使用后及时释放就不会造成内存泄漏,像
    Try
    Finally
      Free;
    end;我想时可以避免的,我想只要在主线程结束前所有创建的对象被释放,应该不会有内存泄漏了吧,像ly_liuyang(Liu Yang) 说的。像pazee(耙子)说的,养成良好的程序代码书写习惯,用那些安全的格式写代码,应该会降低内存泄漏的几率。初学,望大家指正。
      

  8.   

    TStringList的资源要释放,TRect和TPoint的资源要释放吗?String本身就是动态数组,超长String不释放也会占内存,但如何释放好象BoudsCheck根本查不出来,Sleuth QA又没有Free的,烦!
      

  9.   

    http://www.automatedqa.com/downloads/memproof.asp
    有for d6版下载
      

  10.   

    内存管理是个很深奥的东西,否则,操作系统不可能专门分出来一块处理内存管理的!我们写程序的时候,就算做的再好,也不可能把内存100%的释放,内存的释放其实是通过操作系统完成的。当然,如果你写程序估计浪费内存,故意不回收对象的内存的话,那操作系统也么有办法,现在假如你的程序已经告诉这块内存可以交给操作系统分配给其他的应用程序了,按理说,那这块类存就被操作系统100%的回收了,其实不然,操作系统对内存分快的时候可能出现碎片,而对这些碎片的管理队操作系统来说就很重要,而且,对于有些碎片,根本是不可能被回收的,因为有些程序在内存中的位置是不能改变的!现在的操作系统对内存碎片的处理技术是好了很多,而在以前,就是我们常用的win98,对内存碎片的管理还是很不好,这样的话,就算你的程序写得再好,不难以避免时间长了要被终止!
      

  11.   

    我来具体说明一下吧:
    内存变量按大类来分,主要可以分3类:1)全局(静态)变量。这个就不要我说了吧?
    2)自动变量,也就是常说的局部变量,这类变量离开作用域就自动释放。所以象楼上有人问,STRING怎么释放,一般来说,离开了它的作用域,就会自动释放的,不需要你手工去释放。
    3)自由变量。这类变量最麻烦,必须手工申请内存,也必须手工释放。这类变量有自己的作用域,但是生命周期却又是全局的。比如在DELPHI的一个CLASS,即使你是局部变量,超出了作用域,它仍然会存在。这里就是内存泄露最常发生的地方。特别的,如果你使用的是堆,用new创建出来的对象,也都是必须手工释放的。
      最安全的释放,一般就是:
      1)调用释放函数
      2)把原来的变量指向一个空(nil)
      

  12.   

    java里一样有内存泄露。所以楼主说的JAVA不用管理内存,其实是对JAVA的一大误解。更何况,如果希望所有内存释放都依靠垃圾回收去管理,程序的效率一定很低。我举个JAVA内存泄露的例子:下面给出了一个简单的内存泄露的例子。在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个Vector中,如果我们仅仅释放引用本身,那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。Vector v=new Vector(10);
    for (int i=1;i<100; i++)
    {
    Object o=new Object();
    v.add(o);
    o=null;
    }
    //此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
    最后说明:
       不要寄希望于任何工具,希望它们来管理内存。管理内存是程序员应该做的事情。否则,就不是个合格的程序员。OK?
      

  13.   

    foxnt(白羊座神话★天马梦想) 说的也是一知半解!
     考!这里的人,水平都那么烂!
      

  14.   

    zhang21cnboy(沧桑男人) :
       你是一知全解的话,为什么不回答问题?看你上面说的,和没说一样。废话一堆。
      

  15.   

    继续讨论,就是一个空的完全空的窗体,也会发生2处泄漏, 不信各位试试。正版的有没有问题是win2k的内存回收问题,跟delphi无关
      

  16.   

    >>继续讨论,就是一个空的完全空的窗体,也会发生2处泄漏, 不信各位试试。YOUR CODE?