正如其他海报所指出的,这些对象需要明确释放。这通常是通过使用 try..finally 块手动完成的,正如 Ray 所演示的。但是,您应该注意一些例外情况。
组件(TComponent 后代)将 Owner 参数传递给它们的构造函数。如果所有者不是nil,那么所有者组件将获得新组件的所有权并在它被释放时释放它。这就是为什么您不必清理自己的表单的原因;它们连接到 Application 对象,该对象知道如何在程序完成时释放自己。但是,如果您在运行时创建组件,则需要为其分配所有者或将nil传递给构造函数,然后自己释放它。 不要通过释放具有所有者的组件来混合两者。 在某些情况下,这可能会导致双重自由状态。
如果您将实现引用计数的接口对象(主要是 TInterfacedObject 后代)专门称为接口(而不是对象),则引用计数机制将释放它们。当对它们的最后一个接口引用被删除时,它们会自动释放。如果您已将 TInterfacedObject 分配给接口引用,请不要手动释放它。这将引发异常。此外,请注意并非所有具有接口的对象都实现引用计数。大多数只是从 TInterfacedObject 继承的那些。
创建一个对象,使用 try..finally 块,然后释放它并不总是可行的。有时这对您正在做的事情不起作用,特别是如果您将对象分配给某种列表(并制作大量列表)。在这种情况下,使用 TObjectList 是个好主意(或者更好的是,如果您有 D2009,一个 TObjectList),并且 OwnsObjects 属性设置为true。这会导致列表成为其中对象的所有者,并在释放时释放它们,就像组件一样。同样,如果对象由对象列表拥有,则不要手动释放对象。
动态数组(包括字符串)由具有引用计数系统的编译器管理,大多数其他类型的变量在堆栈上分配。你永远不必担心手动释放对象以外的任何东西,除非你在玩指针。
这可能听起来很复杂,但你很快就会习惯的。请记住,每个对象都属于以下三件事之一:另一个对象、接口引用计数系统或您的代码,并且所有者应该在不再需要时释放其所有对象。任何东西都不应该试图释放属于其他东西的东西。(你不能偷窃。)记住这些指导方针,你最终会得到良好的内存管理。您还可以在 DPR 的主例程中设置“ReportMemoryLeaksOnShutdown := true”以获得更多帮助。