form.free、from.close、form:=nil 有什么区别

时间:2022-09-12 13:42:16
form.free、from.close、form:=nil  有什么区别



self.close self.free  self:=nil

跟实例名例如 

obj.close obj.free  obj:=nil

有什么区别





我的一个窗体实例 frmuserop 继承frmbase

frmbase 有一个

fromclose方法

action:=cafree;//窗体释放



然而我在frmuserop窗体中的

formclose方法

使用  frmuserop.free//报错

        self.free;//第二次打开相同窗口报错

        self:=nil;//第二次打开相同窗口报错

       frmuserop:=nil;//正确

这是为什么,请高手指点

13 个解决方案

#1


你都设置为nil了,再访问当然出错了,如果是动态创建的,这样没问题的

#2


所有的窗体都是动态创建的
obj:=Tobj.create(self);

#3


fromclose方法
action:=cafree;//窗体释放     close默认是不会释放,这样设置就自动释放了

这样后就已经free了,再置空就可以了:=nil

或者close里面不自动free,使用 .free   := nil



#4


self 都已经释放了,对象找不到了吧

#5


form.free 销毁对象
from.close 关闭窗体
form:=nil 指针赋值

#6


首先要先接受这么一个概念,任何对象不能自我释放,就如同不能自我创建一样,不能在一个类的成员函数里去释放它的一个实例,为什么我也不太清楚-_-!,可能是一些释放操作必须要在对象范围以外进行,这部分的代码你是看不到的,TObject的destroy隐藏了代码,所以self.free和self:=nil这种写法不对,而frmuserop是个全局变量,所以可以nil,但也可能有潜在的问题,还是在onclose里面Action:=caFree这种方法最好。

#7


form.free 销毁对象
from.close 关闭窗体
form:=nil 指针赋值 
 

#8


在delphi中,所有vcl对象都是指针,你所说的form也是一个指针
form.free:
 收回form指针所指对象分配的内存(调用tform的析构函数释放窗口对象);
from.close:
关闭窗体,from所指的对象并未释放内存,因此还是可以访问的,例如form.name,等等;
form:=nil:
将指针指向空,但分配的内存未释放,这样做会导致内存泄漏。

最好将Form定义为全局变量而非局部变量,因为局部变量超过作用域后指针变量就不可访问了,但分配的对象内存仍然存在,将导致内存泄漏;
收回动态创建的窗口,最好使用FreeAndNil(Form)而不是简单的使用free,便不能用destroy,这样的好处是,由于程序逻辑的需要要再次访问Form时,不会因为form所指内存收回而导致出错。 
设计实际的项目必须彻底搞清这些知识,否则程序是很不稳定。

#9


form.hide:隐蔽窗体,窗体实际上还处于show状态,只不过你看不见罢了。
form.close:关闭窗体但是窗体的在内存里面还是存在!!! 可以随时用show显示出来
form.free:是释放内存的,如果窗体free了用show方法是出不来的,必须要create窗体才行
application.Terminate:整个application中止退出
application.halt中止运行

#10


学习...
这也是我的疑问~~

#11


from:= nil主要实用于窗体打开前检测是否已打开该窗口(窗口关闭时设置from:=nil)

#12


看了以上各位说明,好像很有道理,那谁能解决以下问题:
我在窗口a关闭时执行如下程序   
  if a.caption='a' then   
  begin   
  a.release;   
  Application.CreateForm(Ta,a);   
  a.qy1.close;   
  a.qy1.sql.clear;   
  a.qy1.sql.add('select * from a');   
  a.qy1.open;   
  a.datasource1.dataset:=qy1;   
  a.dbgrideh1.datasource:=a.datasource1;   
  a.show;   
  a.caption:='b';   
  end;   
  if a.caption='b' then   
  begin   
  a.release;   
  Application.CreateForm(Ta,a);   
  a.qy1.close;   
  a.qy1.sql.clear;   
  a.qy1.sql.add('select * from b');   
  a.qy1.open;   
  a.datasource1.dataset:=qy1;   
  a.dbgrideh1.datasource:=a.datasource1;   
  a.show;   
  end;   
  如果新建表单的话,需要几个表单,现在需要一个表单连续显示几屏结果。
  目的是用这种方法在同一个窗口显示几屏结果.显示每问题,但是当用   
  with application.FindComponent('a') as tform do   
  begin   
  当选中的字段是STRING类型时   
  if (tdbgrideh(FindComponent(component)).SelectedField.DataType=ftstring) then   
  showmessage('v');   
  end;时出现错误access violation at address 004284f0 in module 'scgl.exe'.read of address 00000010 如何解决   

#13


该回复于2010-12-06 15:07:00被版主删除

#1


你都设置为nil了,再访问当然出错了,如果是动态创建的,这样没问题的

#2


所有的窗体都是动态创建的
obj:=Tobj.create(self);

#3


fromclose方法
action:=cafree;//窗体释放     close默认是不会释放,这样设置就自动释放了

这样后就已经free了,再置空就可以了:=nil

或者close里面不自动free,使用 .free   := nil



#4


self 都已经释放了,对象找不到了吧

#5


form.free 销毁对象
from.close 关闭窗体
form:=nil 指针赋值

#6


首先要先接受这么一个概念,任何对象不能自我释放,就如同不能自我创建一样,不能在一个类的成员函数里去释放它的一个实例,为什么我也不太清楚-_-!,可能是一些释放操作必须要在对象范围以外进行,这部分的代码你是看不到的,TObject的destroy隐藏了代码,所以self.free和self:=nil这种写法不对,而frmuserop是个全局变量,所以可以nil,但也可能有潜在的问题,还是在onclose里面Action:=caFree这种方法最好。

#7


form.free 销毁对象
from.close 关闭窗体
form:=nil 指针赋值 
 

#8


在delphi中,所有vcl对象都是指针,你所说的form也是一个指针
form.free:
 收回form指针所指对象分配的内存(调用tform的析构函数释放窗口对象);
from.close:
关闭窗体,from所指的对象并未释放内存,因此还是可以访问的,例如form.name,等等;
form:=nil:
将指针指向空,但分配的内存未释放,这样做会导致内存泄漏。

最好将Form定义为全局变量而非局部变量,因为局部变量超过作用域后指针变量就不可访问了,但分配的对象内存仍然存在,将导致内存泄漏;
收回动态创建的窗口,最好使用FreeAndNil(Form)而不是简单的使用free,便不能用destroy,这样的好处是,由于程序逻辑的需要要再次访问Form时,不会因为form所指内存收回而导致出错。 
设计实际的项目必须彻底搞清这些知识,否则程序是很不稳定。

#9


form.hide:隐蔽窗体,窗体实际上还处于show状态,只不过你看不见罢了。
form.close:关闭窗体但是窗体的在内存里面还是存在!!! 可以随时用show显示出来
form.free:是释放内存的,如果窗体free了用show方法是出不来的,必须要create窗体才行
application.Terminate:整个application中止退出
application.halt中止运行

#10


学习...
这也是我的疑问~~

#11


from:= nil主要实用于窗体打开前检测是否已打开该窗口(窗口关闭时设置from:=nil)

#12


看了以上各位说明,好像很有道理,那谁能解决以下问题:
我在窗口a关闭时执行如下程序   
  if a.caption='a' then   
  begin   
  a.release;   
  Application.CreateForm(Ta,a);   
  a.qy1.close;   
  a.qy1.sql.clear;   
  a.qy1.sql.add('select * from a');   
  a.qy1.open;   
  a.datasource1.dataset:=qy1;   
  a.dbgrideh1.datasource:=a.datasource1;   
  a.show;   
  a.caption:='b';   
  end;   
  if a.caption='b' then   
  begin   
  a.release;   
  Application.CreateForm(Ta,a);   
  a.qy1.close;   
  a.qy1.sql.clear;   
  a.qy1.sql.add('select * from b');   
  a.qy1.open;   
  a.datasource1.dataset:=qy1;   
  a.dbgrideh1.datasource:=a.datasource1;   
  a.show;   
  end;   
  如果新建表单的话,需要几个表单,现在需要一个表单连续显示几屏结果。
  目的是用这种方法在同一个窗口显示几屏结果.显示每问题,但是当用   
  with application.FindComponent('a') as tform do   
  begin   
  当选中的字段是STRING类型时   
  if (tdbgrideh(FindComponent(component)).SelectedField.DataType=ftstring) then   
  showmessage('v');   
  end;时出现错误access violation at address 004284f0 in module 'scgl.exe'.read of address 00000010 如何解决   

#13


该回复于2010-12-06 15:07:00被版主删除