这个鸟delphi,气死我了。内存释放的问题问题是这样的。我有两个窗体,form1, 主窗体,form2在projects设为手工创建 。在Form1,上放了一个button1, 在implea..下引用form2.var
  Form1: TForm1;implementationuses Unit2;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(Form2) then
  Form2:=TForm2.Create(Self);
Form2.Show;
//第二次Show的时候Create就不会执行,但是实际上Form2已经不存在了,所以Form2.Show
end;//下面是form2的代码
{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
begin
Close;
end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
action:=cafree;
FORM2:=NIL;
end;end.
另外我在form2上放了一张600*800的bmp格式图象,
当form1第一次调用 form2的时候,占用了500K的内存, 
在关闭form2窗体后,这个图象资源根本就没有释放。只是放了十几k (如果没有图象也是一样,就是一个空窗体), 第二次调用的时候好象资源没占多少。但是当主窗体关闭后,内存又复位了。form2关闭后怎样把form2彻底.不信的大家可以自己做个实验,就两个窗体。

解决方案 »

  1.   

    起始空闲内存        214,996/kb
    点击运行程序显示窗体214,308/kb (就一个窗体+一个button)点击button1弹出form2,208,196/kb点击form2的关闭按钮后 213.994 //没有回到起始的214.308再次点击Form1的button1 启动form2.再点击form2的关闭钮按.     显示的内存为213.994 //关闭主程序,214,856 //比运行前少了几十k
      

  2.   

    delphi vcl 内部有缓冲机制,这对于反复创建、销毁的对象能提高效率!
      

  3.   

    先说明一下, 没有image的空窗体也一样占内存。 拿到还要手工释放image1对象不成。我又不是能过 .create创建的。
      

  4.   

    to myy
    delphi vcl 内部有缓冲机制,这对于反复创建、销毁的对象能提高效率!我的程序不是在调试环境下运行的, delphi 怎么去管理
      

  5.   

    procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Self.Free;
    end;
      

  6.   

    楼上你这么不就等于form2.free; //这个我已经写了。
      

  7.   

    楼主你把自己砍了吧,有你这样设计程序的吗?
    象下面这样实现不是很简单吗?
    with TForm2.Create(Application) do try
      ShowModal;
    finally
      Free;
    end;
      

  8.   

    在project option里有没有把form2定义为手动创建模式?
      

  9.   

    楼上的,如果我写的有问题,我可以砍了我自己,我那写法有问题吗? 不就是一个show, 一个showmodal
      

  10.   

    form2在projects设为手工创建 。
      

  11.   

    老大,写到destory事件中试试!
      

  12.   

    FORM2:=NIL;放到Destroy事件中去.可以的.
      

  13.   

    有位高人是这么说的。 form2.free只是释放了form2所指向的实例(可以理解为form2本身是个指针,内容指向一块内存, 那块内存里存放了form2实例的具体内容)
    form2本是的值并未清空。 而if assigned(form2)其实就等于 if form2 <> nil
    所以第二次调用时会出错, 因为form2这时仍然指向一块已经被释放掉了的内存。 当然不等于nil第二个问题:
    第一次内存增加只是因为当时你程序的堆空间不够, delphi的内存管理机制向windows申请了一块内存。 而这块内存就由delphi帮你管起来了。 form2.free时只是在堆中标记这块内存可用而已, 但并未返回windows。这样当程序再次需要内存时不必向windows再申请了, 直接就使用堆中的空内存就可以了。 这样效率会提高很多。 
    同意的举hand
      

  14.   

    问题还没解决,我通过BoundsChecker工具检测,就一个空的窗体, 也会检测出内存泄漏, 我装的是delphi6+sp2,每运行一次,内存少12k
      

  15.   

    我用的是子窗口的形式。我用form2:=nil;后,form2就彻底关闭了,第二次执行时候完全正确
      

  16.   

    主要问题在于,Form2.Free后,如果不把Form2 := Nil那么在Assign(Form2)的时候不会判断出空。
      

  17.   

    form2.free只是释放了form2所指向的实例(可以理解为form2本身是个指针,内容指向一块内存, 那块内存里存放了form2实例的具体内容)
    form2本是的值并未清空。 而if assigned(form2)其实就等于 if form2 <> nil
    所以第二次调用时会出错, 因为form2这时仍然指向一块已经被释放掉了的内存。 当然不等于nil第二个问题:
    第一次内存增加只是因为当时你程序的堆空间不够, delphi的内存管理机制向windows申请了一块内存。 而这块内存就由delphi帮你管起来了。 form2.free时只是在堆中标记这块内存可用而已, 但并未返回windows。这样当程序再次需要内存时不必向windows再申请了, 直接就使用堆中的空内存就可以了。 这样效率会提高很多。 --------------------同意 . 也谢谢解惑,其实,任何一个变量名都可以理解为一个指向该变量实例的指针 。
      

  18.   

    都存在一个Free指向空间,Nil自身 的问题。 Try ......
      

  19.   

    在Form2的OnDestory事件中把Form2设为nil就可以了。
      Form2 := nil;
    还有别砍Delphi 啊,我觉得是不错的啊!呵呵!
      

  20.   

    看来你的刀刃不够锋利,因为Delphi还在,你还在。
    你的钻研精神值得大家学习。以下为本人拙见,供你参考:
    (1)你的程序思路从设计上来说没有什么问题。我理解为,由于Form2作为非模式化显示,因此每次按下Form1.Button1时需要检查Form2是否已经创建,如果未创建则进行创建,然后显示Form2。而对于Form2,则关闭时就释放资源。如果从内存消耗的角度考虑,那么这种思路似乎是正确的,但Delphi程序和C++在这方面是有差别的。也就是说,Delphi产生的可执行文件中都引入了自动管理内存的代码,这也是Object Pascal编程中不常使用指针来管理内存的原因。事实上,只要你申请内存时使用的方法得当,那么你几乎可以不必考虑是否记得把它们释放,Delphi在你的程序中已经嵌入了安全机制,这也是Delphi程序比C++程序尺寸较大的原因。
    (2)你的代码中关于Assigned函数有一些瑕疵。简单地说,你对Assigned函数的理解还不够全面和准确。对于一个有效的指针变量P,Assigned(P)等价于(P <> nil),或者等价于(@P <> nil)。而对于一个无效的指针变量P,那么Assigned(P)总是返回True。查看Assigned函数的相关帮助和帮助中的例子可以获得详细信息。因此,即便你的Form2已经释放(严格地说,是Form2变量指向的对象实例被释放,此时Form2仍指向原来的地址,但指向的地址已经无效),但如果没有将其赋值为nil,那么Assigned(Form2)仍总返回True(仅当第一次判定时返回False,因为Delphi程序自动将变量、指针和动态变量等初始化为“0”值,如nil,空串等)。
    (3)你对Self和Create的用法有些不妥。事实上,规范的结构是:窗口的所有者是Application,窗口中各组件的所有者是相应的窗口。因此,写成Form2 := TForm2.Create(Application)更规范。
    (4)即使是按照你的程序代码,也不会有所谓“内存泄露”的问题,我是指当程序终止时不会有未释放的内存。相信你所用的检测工具不完善。因为Windows本身也有内存缓冲机制,因此有时获得的“可用内存”并不是准确的值,严格地说,“可用”内存至少包括两部分,一部分是内存缓冲区中的,一部分是尚未使用过的。而一般的内存检测工具只检测“尚未使用过的”作为“可用内存”。
    我能解释的也就这些了,更多的信息见Delphi帮助中有关内存管理的主题。
      

  21.   

    对于你所期望的运行结果,我有如下建议:
    设置一个全局变量来标记Form2当前是否有效和可用。初始值为False。每次创建时检查该该变量。创建Form2时为True,释放Form2时置为False。点击Form1.Button1时就不必担心发生异常了。另外,建议创建Form2时以Application作为Owner,而不要以Form1作为Owner。
    还有一条建议,根据Delphi和Windows各自的缓冲机制,运行时反复动态创建和销毁窗口并不会明显减少内存开销。因此,只需要考虑运行速度,即在首次使用时创建,应用程序终止时一并销毁。运行期间只需要反复调用Show和Hide即可。
      

  22.   

    用show和showmodel显示的窗体在释放内存时是有区别的:
     用showmodle:需在destory释放
     用show :在formclose中就可释放
      

  23.   

    用show和showmodel显示的窗体在释放内存时是有区别的:
     用show :需在destory释放
     用showmodle:在formclose中就可释放
      

  24.   

    FORM2:=NIL;放到Destroy事件中去.可以的.楼主说这可不行,为什么不行,你有试过吗?实践出真知!
      

  25.   

    这么多人阻止楼主砍Delphi,看来楼主只好砍自己了。大家快来帮帮忙吧,哈哈!
      

  26.   

    FORM:=NIL;是可以的,它只有一个空地址了
      

  27.   

    楼主的写法有点问题
    在TForm2
    procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      action:=cafree;
      FORM2:=NIL;
    end;FORM2:=NIL;这句是非常糟糕的,假设我定义 frmForm3:TForm2,将会出现不可预期的错误!!if not Assigned(Form2) then
      Form2:=TForm2.Create(Self);
    等也有一点问题
    这种写法唯一的可行性是Form2是全局的变量,否则问题很多,可改为从Screen.Forms中去寻找
    Action:=caFree;这句已经释放了内存
      

  28.   

    听你这么一讲, 了解了一些, 每次运行关闭应用程序少那么二三十k,是正常的事情对吧! 那我就不管他的。 但我保证子窗体一定全都释放了。只是在关闭主程序的时候有那么一点点
    没有释放,我用人存检测工具看了一下, 的确有内存泄 漏, 那怕就一个空的窗体都会有。在程序用程序里我是这么做的。if not Assigned(Form2) then
     try
       form2:=Tform2.create(application);
       Form2.modal;
     finally
       Form2.free;  //这两句写在Form2的onclose里 应该是一样!没有意见吧
      Form2:=nil;
    end;
     
    结束应用程序,application.terminate; 
      

  29.   

    function TfMain.FindForm(const FormClassName: string; const StartIndex: Integer): Integer;
    var
      i: integer;
    begin
      Result := -1;
      with Screen do
      for i := StartIndex to FormCount - 1 do
      begin
        with Forms[i] do
        if ClassName = FormClassName then
        begin
          Result := i;
          Exit;
        end;
      end;
    end;  Index := FindForm('TfBrowseOperators', 0);
      if Index >= 0 then
      with Screen.Forms[Index]  do
        begin
          Show;
          WindowState := wsNormal;
        end
      else
        with TfBrowseOperators.Create(Self) do Show;
      

  30.   

    在from2 的onclose写入如下代码即可:
    Action:= caFree;自己技术不行不要骂天。
    快给分了。
      

  31.   

    第一个问题我的解决方法是把
    if not Assigned(Form2) then
    改成
    if Form2=nil then
    这样就可以保证第一次创建的form2关闭后(form2=nil已执行)可以再一次创建。使用Assinged(Form2)总有问题,很不爽。Form2是delphi定义的一个变量(Form2:TForm2),使用它来创建TForm2窗体挺好的,我个人认为再定义一个Tform2变量来创建Tform2窗体反而不好控制
      

  32.   

    这样做看看怎样:
    使用消息传递来Free那个Form2,同时使Form2:=nil;
    自定义消息,或是用Public成员访问也是可以的
    Form2.onclosequery:
    form1.trytofreeform2; // 或sendmessage..
    Form1收到消息以后释放Form2
      

  33.   

    同意cnsuyong(小可)。
    Delphi 和C比起来确实不一样,比如说内存释放,C没有这么复杂的控制:
    free(ptr) 此时ptr=null了,而Delphi 中则:Ptr.free;ptr :=nil;不知道不加后一句会有什么用途呢?从这个角度来讲,Assigned(form2)和if form2=nil 确实不一样的。