我有以下示例代码 有人可以解释为什么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;
答案 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
,但基本概念完全相同。