【问题标题】:Can I use .Create(Nil) instead of .Create(Application)我可以使用 .Create(Nil) 而不是 .Create(Application)
【发布时间】:2012-08-02 04:40:44
【问题描述】:

我有一个具有 TComponent 变量的单元,我在单元初始化时创建此组件,如下所示:

var
  XComp: TComponent;
.
.
.
.

initialization
begin
  XCom := TComponent.Create(Application);
end;

安装单元后,当我关闭 Delphi 时,它给我一个访问冲突错误消息 (EAccessViolation)

但是当我将我的创建者更改为如下时

initialization
begin
  XCom := TComponent.Create(nil);
end;

一切都很好...我想知道区别?什么更好?

注意:错误仅在关闭 delphi 时出现(意味着在设计时)。

谢谢。

【问题讨论】:

  • 这里是one of the follow ups
  • 您在initialization 部分创建XCom。你也有一个finalization 部分可以释放它吗?

标签: delphi delphi-xe2 tcomponent


【解决方案1】:

当你使用时

XCom := TComponent.Create(Application);

您让应用程序成为 XCom 的所有者。当应用程序终止时,它将负责销毁 XCom,因为它是所有者。

当你这样做时

XCom := TComponent.Create(nil);

没有人是 XCom 的所有者,您必须在应用程序终止时自行释放它。

您可能遇到了异常,因为您手动释放了 XCom,然后应用程序也尝试释放 XCom。

【讨论】:

  • +1。作为一般指南:当你自己释放对象时使用nil,如果你不是并且你希望它为你清理或者如果你有可能无法释放它,请使用Application自己。
  • @birger:如果组件编码正确,它会在释放时将自己从所有者的组件列表中删除(在这种情况下:应用程序)。所以理论上不应该发生AV。我认为可能是相反的情况:该组件已经被应用程序释放,然后程序试图访问它。如果我正确解释了这个问题,这是设计时包中的一个组件,并且 AV 出现在 Delphi IDE 中,所以这有点复杂。
【解决方案2】:

基本上两者都是允许的,即使你有这样的代码也不应该产生 AV:

MyComp := TMyComp.Create(Application);
try
  {...}
finally
  MyComp.Free;
end;

这是因为正确编码的组件在被销毁时会从其所有者的组件列表中删除。

我认为这里的问题可能是该组件已被应用程序对象释放,后来一些代码尝试访问它。也许您的代码中有一个 finalize 部分,是吗?或者你可能有混合的对象和接口,而引用计数会帮助你。

要调试您的问题,您可以通过将包的“主机应用程序”设置为 Delphi (C:\Program Files\\BDS\\Bin\bds.exe) 在调试器中运行 IDE。 并在组件的析构函数中设置断点。这样您就可以知道它在哪里被释放以及 AV 发生在哪里。

【讨论】:

    猜你喜欢
    • 2011-04-13
    • 2012-03-23
    • 1970-01-01
    • 2011-02-20
    • 2017-11-18
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    相关资源
    最近更新 更多