发布后Delphi XE10.2表单不为零

时间:2018-04-20 21:38:43

标签: forms delphi

我在Delphi中使用多年的技术已不再适用,因为我创建的表单在发布之后并未设置为nil。这是一些示例代码:

type 
  TAboutForm = class(TForm);
  end;

function ShowAboutForm: TModalResult;
function ShowAboutForm2: TModalResult;

implementation

var
  FAboutForm: TAboutForm;

{$R *.dfm}

function AboutForm: TAboutForm;
begin
  if not Assigned(FAboutForm) then
    FAboutForm := TAboutForm.Create(Application);
  Result := FAboutForm;
end;

function ShowAboutForm: TModalResult;
begin
  with AboutForm do
    try
      Result := ShowModal;
    finally
      Release;
    end;
end;

function ShowAboutForm2: TModalResult;
var
  AAboutForm: TAboutForm;
begin
  AAboutForm := AboutForm;
    try
      Result := AAboutForm.ShowModal;
    finally
      AAboutForm.Release;
      AABoutForm := nil;
    end;
end;

ShowAboutForm和ShowAboutForm2都没有第二次工作。两者都抛出访问冲突,因为任何一种方法都没有将FAboutForm设置为nil - 即使ShowAboutForm2显式地将局部变量设置为nil - 因此它不会在AboutForm中重新创建。我发现让代码工作的唯一方法是:

function ShowAboutForm3: TModalResult;
begin
  fAboutForm := AboutForm;
  try
    Result := fAboutForm.ShowModal;
  finally
    fAboutForm.Release;
    fAboutForm := nil;
  end;

这是处理创建和发布表单的合适方式吗?除非直接引用已实现的var,否则为什么表单不会被释放?

1 个答案:

答案 0 :(得分:9)

你的技术一直都被打破了。如果它曾经奏效,那只是偶然的。

在第一个示例中,您只是发布表单,您永远不会将其全局引用设置为nil,因此它将指向表单对象实例所在的无效内存。

在第二个示例中,您将表单对象的本地引用设置为nil,而不是稍后测试的全局引用。由于您使用Assigned进行测试的引用从未设置为nil,因此它也指向无效内存。

变量(reference)仅表示指向真实对象所在内存的指针。您可以拥有指向同一对象实例的多个指针。但是这些参考文献中的每一个都是独立的。如果您将其中一个设置为nil或任何其他值,则其他引用仍将指向之前指向的任何值。

正如您已经发现的那样,真正的解决方案是将fAboutForm引用设置为nil,因为这是您使用Assigned测试的引用。

此外,由于您使用全局变量来保留引用并在AboutForm函数中分配该变量,因此您实际上不必在ShowAboutForm3中使用{{1}再次分配该变量}}。

它对你的代码功能没有任何影响,它会起到同样的作用,但它有点乱。