我有2个表单,我通过传递参数表单的函数释放form2。 德尔福关闭了表格,但仍然按照指定继续。
破坏表格后,仍然显示已分配! 见下面的例子:
***对不起我的英语,我使用的是谷歌翻译
{Procedure to destroy form}
procedure TForm1.Destruir(aForm: TForm);
begin
FreeAndNil(aForm);
end;
{button create form}
procedure TForm1.btnCreateClick(Sender: TObject);
begin
Form2:= TForm2.Create(nil);
Form2.Show;
end;
{button Destroy Form}
procedure TForm1.btnDestroyClick(Sender: TObject);
begin
Destruir(Form2);
end;
{button Verify}
procedure TForm1.btnVerifyClick(Sender: TObject);
begin
if Assigned(Form2) then
ShowMessage('Assigned')
else
ShowMessage('unAssigned');
end;
答案 0 :(得分:2)
您需要将参数传递给Destruir
作为var
参数,以便对传递的参数进行修改以修改传递的变量,而不是它的本地副本。
procedure TForm1.Destruir(var aForm: TForm);
begin
FreeAndNil(aForm);
end;
当然,这个功能有点不必要,因为您也可以直接拨打FreeAndNil
而不是拨打Destruir
。
答案 1 :(得分:2)
这正是我认为Delphi在Destroy
,Free
和FreeAndNil
上的文档有些不足的原因。它会导致对何时分配引用或不分配引用的不切实际的期望,以及对常见内存/资源管理错误的理解不足。
当您有多个引用单个对象(或表单)的变量时,它们都被视为"已分配"因为他们有价值;指向共享对象的相同值。
这些参考文献中的任何一个都可用于"销毁"物体。上面的3个方法中的任何一个都足够了。 FreeAndNil
会将一个引用设置为 nil 。但 所有其他引用将完全不知道对象已被销毁 ,仍将被视为"已分配"。
在您的代码中,procedure TForm1.Destruir(aForm: TForm);
将其参数按值。这意味着它会复制输入引用。换句话说,你有两个参考。
[Destruir-aForm]-----\
[The actual form instance]
[Form2]--------------/
因此,当您致电FreeAndNil(aForm);
时,您只需将Destruir-aForm
设置为 nil 。并且Form2
仍然分配给无效对象。
[Destruir-aForm]--(nil)
[Nothing here, Form was destroyed.]
[Form2]--------------/
因此,解决问题的方法是使用 var 传递参数 by-reference 。 (注意: const 类似于 var ,因为它也通过引用传递,但有限制,您不能更改它。 )
因此,如果你声明procedure TForm1.Destruir(var aForm: TForm);
,那么内存看起来会像下面那样:
[The actual form instance]
[Destruir-aForm]=>[Form2]--------------/
现在,当FreeAndNil(aForm);
将aForm
设置为 nil 时,它还会将Form2
设置为 nil ;因为它们都是相同的东西。即Destruir-aForm
不仅仅是一个副本。
请注意,您可能在Destruir
使用错误的参数声明无意中创建了对Form2的引用的副本。
但是当你明确地对同一个对象有多个共享引用时,原理是一样的。 FreeAndNil
只能将其中一个引用设置为 nil 。您需要以一种可以确保不会尝试重复使用无效引用的方式编写应用程序。