这个鸟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彻底.不信的大家可以自己做个实验,就两个窗体。
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彻底.不信的大家可以自己做个实验,就两个窗体。
点击运行程序显示窗体214,308/kb (就一个窗体+一个button)点击button1弹出form2,208,196/kb点击form2的关闭按钮后 213.994 //没有回到起始的214.308再次点击Form1的button1 启动form2.再点击form2的关闭钮按. 显示的内存为213.994 //关闭主程序,214,856 //比运行前少了几十k
delphi vcl 内部有缓冲机制,这对于反复创建、销毁的对象能提高效率!我的程序不是在调试环境下运行的, delphi 怎么去管理
begin
Self.Free;
end;
象下面这样实现不是很简单吗?
with TForm2.Create(Application) do try
ShowModal;
finally
Free;
end;
form2本是的值并未清空。 而if assigned(form2)其实就等于 if form2 <> nil
所以第二次调用时会出错, 因为form2这时仍然指向一块已经被释放掉了的内存。 当然不等于nil第二个问题:
第一次内存增加只是因为当时你程序的堆空间不够, delphi的内存管理机制向windows申请了一块内存。 而这块内存就由delphi帮你管起来了。 form2.free时只是在堆中标记这块内存可用而已, 但并未返回windows。这样当程序再次需要内存时不必向windows再申请了, 直接就使用堆中的空内存就可以了。 这样效率会提高很多。
同意的举hand
form2本是的值并未清空。 而if assigned(form2)其实就等于 if form2 <> nil
所以第二次调用时会出错, 因为form2这时仍然指向一块已经被释放掉了的内存。 当然不等于nil第二个问题:
第一次内存增加只是因为当时你程序的堆空间不够, delphi的内存管理机制向windows申请了一块内存。 而这块内存就由delphi帮你管起来了。 form2.free时只是在堆中标记这块内存可用而已, 但并未返回windows。这样当程序再次需要内存时不必向windows再申请了, 直接就使用堆中的空内存就可以了。 这样效率会提高很多。 --------------------同意 . 也谢谢解惑,其实,任何一个变量名都可以理解为一个指向该变量实例的指针 。
Form2 := nil;
还有别砍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帮助中有关内存管理的主题。
设置一个全局变量来标记Form2当前是否有效和可用。初始值为False。每次创建时检查该该变量。创建Form2时为True,释放Form2时置为False。点击Form1.Button1时就不必担心发生异常了。另外,建议创建Form2时以Application作为Owner,而不要以Form1作为Owner。
还有一条建议,根据Delphi和Windows各自的缓冲机制,运行时反复动态创建和销毁窗口并不会明显减少内存开销。因此,只需要考虑运行速度,即在首次使用时创建,应用程序终止时一并销毁。运行期间只需要反复调用Show和Hide即可。
用showmodle:需在destory释放
用show :在formclose中就可释放
用show :需在destory释放
用showmodle:在formclose中就可释放
在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;这句已经释放了内存
没有释放,我用人存检测工具看了一下, 的确有内存泄 漏, 那怕就一个空的窗体都会有。在程序用程序里我是这么做的。if not Assigned(Form2) then
try
form2:=Tform2.create(application);
Form2.modal;
finally
Form2.free; //这两句写在Form2的onclose里 应该是一样!没有意见吧
Form2:=nil;
end;
结束应用程序,application.terminate;
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;
Action:= caFree;自己技术不行不要骂天。
快给分了。
if not Assigned(Form2) then
改成
if Form2=nil then
这样就可以保证第一次创建的form2关闭后(form2=nil已执行)可以再一次创建。使用Assinged(Form2)总有问题,很不爽。Form2是delphi定义的一个变量(Form2:TForm2),使用它来创建TForm2窗体挺好的,我个人认为再定义一个Tform2变量来创建Tform2窗体反而不好控制
使用消息传递来Free那个Form2,同时使Form2:=nil;
自定义消息,或是用Public成员访问也是可以的
Form2.onclosequery:
form1.trytofreeform2; // 或sendmessage..
Form1收到消息以后释放Form2
Delphi 和C比起来确实不一样,比如说内存释放,C没有这么复杂的控制:
free(ptr) 此时ptr=null了,而Delphi 中则:Ptr.free;ptr :=nil;不知道不加后一句会有什么用途呢?从这个角度来讲,Assigned(form2)和if form2=nil 确实不一样的。