假设我的表单是TFormOther = class(TForm, IMyInterface)
,其中
type
IMyInterface = interface
['{50E7E215-A8EA-4A1C-9F1E-018E4A76DCBD}']
procedure DoSomething;
end;
和
TFactory = class(TInterfacedObject)
public
procedure MakeIt;
end;
procedure TFactory.MakeIt;
var
LMyIntf: IMyInterface;
begin
LMyIntf := TFormOther.Create(nil);
LMyIntf.DoSomething;
// (LMyIntf as TFormOther).Free; This is wrong and gives the classic:
// FastMM has detected an attemp to use an interface of a freed object.
end;
如果我不释放TFormOther示例,就会泄漏内存。
我知道我可以在TFormOther.FormClose
中做Action := TCloseAction.caFree
,但这是唯一和最好的方法吗?
这个Will an interface-implementing form free itself when there are no more references to it?帮助很大,但没有说明应该如何释放窗体。
1条答案
按热度按时间dfty9e191#
使用
(LMyIntf as TFormOther).Free;
通过其接口引用直接释放窗体问题是,接口引用将比窗体对象示例寿命长当该接口超出范围时,在过程结尾部分,编译器插入了对
_IntfClear
的调用以完成LMyIntf
引用,最终将在已销毁的窗体示例上调用_Release
方法。若要避免这种情况,您必须在释放表单之前明确清除界面。这需要额外的对象变数,您可以透过这个变数呼叫
Free
来释放表单。当通过
FromClose
事件处理程序释放窗体时,只有在释放时没有活动接口引用窗体的情况下,这种释放才能完美地工作。讨论通用代码时,很难说哪种方法更好,但是当使用FormClose
事件时,可能很难确保此时没有活动接口,并且这样的代码可能更难遵循。