在 Delphi 中,将所有者设置为 Application 而不是 nil 有啥好处?

Posted

技术标签:

【中文标题】在 Delphi 中,将所有者设置为 Application 而不是 nil 有啥好处?【英文标题】:in Delphi, what is the benefit of setting owner as Application instead of nil?在 Delphi 中,将所有者设置为 Application 而不是 nil 有什么好处? 【发布时间】:2020-07-16 09:24:39 【问题描述】:

“应用程序”是 VCL 的一部分,因此不是线程安全的(可能是在维护它所拥有的非线程安全组件列表)。

我正在处理的项目有几个实例,其中 Application 设置为 Owner,而 Self 不是一个选项(类方法)。 我想传递“nil”,因为该变量在此函数结束时被释放。

假设有人忘记释放应用程序拥有的变量:

当应用程序关闭时,内存被释放。 但我也读到 Windows 会跟踪分配给每个进程的内存。因此,理论上,如果一个 nil 拥有的变量没有被释放,Windows 会在应用程序/进程终止时释放它。

那么,将所有者设置为 Application 而不是 Nil 有什么好处?

以下问题讨论了释放 nil 拥有的 var 的责任,但停在那里:

What is the meaning of nil owner in component constructor

【问题讨论】:

【参考方案1】:

虽然系统会在进程终止时释放内存,但执行期间的泄漏是一个潜在问题。如果一个程序执行重复的操作,并且每次都泄漏内存,那么这些泄漏会随着时间的推移而累积并最终导致内存不足的情况。

对于应用程序单例对象拥有的组件,可以看到相同的行为。如果它们没有被显式销毁,那么它们只有在应用程序终止时才会被销毁。同样,随着流程的执行,这些泄漏可能会随着时间的推移而累积。

检测泄漏的常规方法是在执行期间跟踪所有分配,然后,作为进程终止的最终行为,检查所有分配是否具有匹配的解除分配。此功能由各种工具提供,但在 Delphi 上下文中,FastMM 内存管理器是提供此功能的最常用工具。

如果您创建的组件归应用程序对象所有,但没有显式销毁它,则在执行泄漏检查程序时它不会显示为已泄漏。这是不可取的,因为您确实存在未检测到的泄漏。

这个论点得出的结论是,在您描述的场景中最好使用无主组件。

另一方面,有时您创建的组件希望与应用程序对象一样长,并且可能很难在代码中找到明确销毁它们的好地方。在这种情况下,由应用程序对象拥有是一个好方法。这正是所有者机制的设计目的。

我的经验法则:

    如果组件是由流系统创建的(即表单),它将使用所有权机制来确保正确的生命周期管理。你在代码中无所事事。 如果您在代码中显式创建组件,那么最好遵循正常的创建模式并在代码中显式销毁它。在这种情况下,使组件成为无主的。 如果您无法轻松找到销毁组件的好地方,并且可以将其生命周期绑定到另一个组件(即应用程序),则将该组件作为所有者传递。

回到你问的问题。您询问了使用应用程序对象作为所有者有利的原因。如上所述,在许多情况下,让这些组件无主实际上是有利的。但有时将应用程序对象作为所有者也是有利的。

总之,没有单一的硬性规则可以遵循。您需要了解所有权的含义,然后为每个组件选择合适的所有者,这可能因情况而异。

【讨论】:

当组件归应用程序所有时,我肯定遇到过 FastMM 不报告的情况。至于你的第三点,这绝对是有道理的,谢谢。如果您不介意,我已经编辑了问题以添加一个最初被遗忘的点 FastMM 不会报告应用程序拥有的组件的泄漏,因为它将在终止时被销毁。但是,如果它是您的程序重复创建的对象,那么它仍然是泄漏并且可能导致内存不足。我试图在答案中解释这一点。在终止时销毁而不是在不再使用时销毁的对象仍然是泄漏,但经典泄漏检测工具无法检测到。 我回滚了您的编辑。这是一个完全不同的问题。将其作为一个新问题提出。

以上是关于在 Delphi 中,将所有者设置为 Application 而不是 nil 有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi 设置程序图标为系统默认图标

打开 Windows Explorer 目录,选择特定文件(在 Delphi 中)

Delphi,可以仅将表单模式设置为特定的父表单吗?

delphi 有关父窗口的问题

delphi中的ApdComPort控件在哪,谢谢

dbgrid 列 delphi