为什么 TInterfacedObject 的后代不被垃圾回收?
我有一个基于 TInterfacedObject 的类。 我将它添加到 TTreeNode 的 Data 属性中。
TFacilityTreeItem=class(TInterfacedObject)
private
m_guidItem:TGUID;
m_SomeOtherNode:TTreeNode;
public
end;
我创建了这个对象的许多实例& 假设因为它们是引用计数的,所以我不需要释放它们。 那会很方便。
然而,当检查这个时,我打开了 ReportMemoryLeaksOnShutdown 并发现它们毕竟没有被释放。
这些对象是在放置在主窗体上的框架中创建的。 在主窗体的 FormClose 中,我清除了树节点,以便释放每个对象。
发生了什么?
感谢您的帮助!
i have a class based on TInterfacedObject. i add it to TTreeNode's Data property.
TFacilityTreeItem=class(TInterfacedObject)
private
m_guidItem:TGUID;
m_SomeOtherNode:TTreeNode;
public
end;
i create many instances of this object & had assumed that because they're reference counted, i shouldn't need to Free them. that'd be handy.
however, when checking this, i turned on ReportMemoryLeaksOnShutdown and found they're not being freed after all.
these objects are being created in a frame that's placed on the main form. in the main form's FormClose, i clear the tree nodes such that every object should be freed.
what's happening?
thank you for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
TInterfacedObject 本身不进行引用计数,只有接口才进行引用计数。 您可以使用 TInterfacedObject 实现接口,这基本上节省了您自己实现引用计数方法的精力。 不幸的是,它在您的情况下仍然不起作用:编译器不知道您正在为 TTreeNode.Data 属性分配接口,因为它没有声明为接口而是指针。 因此会发生各种奇怪的事情:
一旦您尝试通过 .Data 属性访问对象,您就会遇到访问冲突。
因此,在这种情况下,不要为接口而烦恼,您可以让它工作,但它会比它值得的付出更多的努力。
TInterfacedObject itself is not reference counted, only interfaces are. You can implement interfaces using TInterfacedObject which basically saves you the effort of implementing the reference counting methods yourself. Unfortunately it still will not work in your case: The compiler does not know that you are assigning interfaces to the TTreeNode.Data property since it is not declared as an interface but as a pointer. So all kinds of weird things will happen:
As soon as you try to access your object through the .Data property, you will get an access violation.
So, don't bother with interfaces in this case, you could get it to work, but it will be much more effort than it is worth.
您应该将字段/变量声明为接口
要访问字段,您应该在 IFacilityTreeItem 接口中声明属性,并使用 Getters 和 Setters。
You should declare the Field/Variable as Interface
To access your fields, you should declare properties in IFacilityTreeItem Interface, with Getters and Setters.
正如 dummzeuch 所说,你可以让它工作与接口,但它需要更多的代码,因为 TTreeNode 的 Data 属性是一个指针。 对于任何想知道如何做到这一点的人,此链接有一个示例如何为 TListItem 执行此操作(对于 TTreeNode 几乎相同)。 您可能还会发现阅读有关接口和后续内容的部分很有用该页面上有关引用计数的部分。
As dummzeuch said, you can get this to work with interfaces, but it takes some more code since the Data property of a TTreeNode is a pointer. For anyone wondering how to do that, this link has an example of how to do it for TListItem (it's pretty much the same for TTreeNode). You may also find it useful to read the section about interfaces and subsequent section about reference counting on that page.