如何从内存分配中完成释放子表单

时间:2017-11-21 17:48:39

标签: delphi

我有以下示例代码 有人可以解释为什么delphi编译器不会释放所有内存分配 对于对象,所以零检查总是如此。即时通讯使用释放方法来销毁TLoginForm我不使用自由方法,因为当一些接口事件在空闲之前或之后被调用时,这给了我异常。

type
  TMainForm = class(TForm)
  {some stuf}
  public
    procedure Create(AOwner: TComponent); override;
    procedure doLogout();
  end;

  TChildBase = class(TForm)
  {some stuf}
  public
    procedure Create(AOwner: TComponent); override;
  end;

  TLoginForm = class(TChildBase)
  public
    procedure doLogin();
  end;

var
  MainForm: TMainForm; {<== created automaticaly at runtime}
  LoginForm: TLoginForm; {<== created at create event in TMainForm}

implementation

{TLoginForm}
procedure TLoginForm.doLogin;
begin
  if true then
  begin
    { Do Interfaced Event to main form }
    Release;
  end;
end;

procedure TMainForm.Create(AOwner: TComponent);
begin 
  inherited;
  FormStyle := fsMDIForm;
  LoginForm := TLoginForm.Create(Application); {Create login form}
end;

procedure TMainForm.doLogout;
begin
  { Do Interfaced Event to Child Form except TLoginForm to close}

  if LoginForm <> nil then    {<== this still alocated at memory}
    LoginForm := TLoginForm.Create(Application)
  else
    LoginForm.Show; {<== Error raised here.}
end;

2 个答案:

答案 0 :(得分:2)

Release()只是一种延迟的破坏。它向表单发布CM_RELEASE消息,然后表单在处理该消息时自行调用Free

释放Form对象(或任何其他对象)并不会自动将任何指向该对象的指针设置为nil。您必须在自己的代码中手动执行此操作。在这种情况下,您可以在LoginForm的析构函数或TLoginForm事件中将全局OnDestroy指针设置为nil。

您也可以考虑使用TLoginForm.OnClose事件,而不是直接调用Release()doLogin()调用Close(),当表单实际关闭时,将事件的Action参数设置为caFree,以便表单自行释放(通过Release())。但是,您仍然必须手动将全局LoginForm指针设置为nil

答案 1 :(得分:1)

您的代码中没有任何地方将变量LoginForm设置为nil。因此,即使它所引用的对象被破坏,它仍然保留其值。如果您希望将此变量设置为nil,则必须明确地执行此操作。

您应该会发现相关问题的答案有用:https://stackoverflow.com/a/8550628/

从本质上讲,通过这个简单的例子可以更好地理解你的问题背后的问题:

obj := TObject.Create;
obj.Free;
Assert(Assigned(obj));

销毁对象不会清除引用它的变量。

是的,在您的代码中,您使用Release而不是Free,但基本概念完全相同。