我可以使用.Create(Nil)来代替.Create(Application)吗?

7

我是一名有用的助手,可以为您翻译文本。

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

var
  XComp: TComponent;
.
.
.
.

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

在安装完该单元后,关闭Delphi时会出现访问违例错误消息(EAccessViolation)。

但当我把我的创建者更改为以下内容时

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

一切都进行得很顺利...我想知道它们之间的区别是什么?哪一个更好一些呢?
注:只有在关闭Delphi(即在设计时)时才会出现该错误。
谢谢。

这里是其中一个后续问题 - TLama
6
你正在初始化部分创建XCom。你是否也有一个finalization部分来释放它? - Ken White
2个回答

13
当你使用时,

XCom := TComponent.Create(Application);

您需要将Application作为XCom的所有者。当应用程序终止时,它会负责销毁XCom,因为它是所有者。

当您执行以下操作时:

XCom := TComponent.Create(nil);

在应用程序终止时,没有人是XCom的所有者,您需要自己释放它。

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


5
一般指导方针:如果你将自己释放对象,请使用“nil”,如果不需要自行释放并希望由系统清理或者有可能无法自己释放,可以使用“Application”。 - Ken White
1
@birger:如果组件编码正确,当它被释放时,它将从所有者(在本例中为应用程序)的组件列表中删除自身。因此理论上不应该发生AV错误。我认为可能是另一种情况:组件已经被应用程序释放,并且程序尝试在之后访问它。如果我正确解释了问题,那么这是一个设计时包中的组件,并且AV错误发生在Delphi IDE中,所以这有点复杂。 - dummzeuch

2

基本上两种方式都是允许的,即使你有如下代码,也不应该导致AV:

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

这是因为如果组件被正确编码,当其被销毁时,它将从其所有者的组件列表中移除自身。
我认为问题可能在于应用程序对象已经释放了该组件,而后来某些代码尝试访问它。也许你的代码中有一个 finalize 部分做了这个事情?或者你可能混用了对象和接口,并且参考计数搞砸了。
为调试此问题,你可以通过将包的“主机应用程序”设置为Delphi(C:\ Program Files \ BDS \ Bin \ bds.exe),在调试器中运行IDE,并在组件的析构函数中设置断点。这样你就能找出它被释放的地方以及AV出现的地方。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接