delphi reference-counting tinterfacedobject

delphi - ¿Por qué no se recogen los descendientes de la basura TInterfacedObject?



reference-counting (3)

tengo una clase basada en TInterfacedObject. Lo agrego a la propiedad de datos de TTreeNode.

TFacilityTreeItem=class(TInterfacedObject) private m_guidItem:TGUID; m_SomeOtherNode:TTreeNode; public end;

creo muchas instancias de este objeto y asumí que, debido a que son referencias contadas, no debería necesitar liberarlas. eso sería útil.

sin embargo, cuando revisé esto, activé ReportMemoryLeaksOnShutdown y descubrí que no se liberarían después de todo.

estos objetos se están creando en un marco que se coloca en la forma principal. en FormClose de la forma principal, borro los nodos de árbol de modo que cada objeto se libere.

¿Qué esta pasando?

¡Gracias por tu ayuda!


Debe declarar el campo / variable como interfaz

IFacilityTreeItem = IInterface end; TFacilityTreeItem=class(TInterfacedObject, IFacilityTreeItem) private m_guidItem:TGUID; m_SomeOtherNode:TTreeNode; end; var Item: IFacilityTreeItem; // Variable as Interface begin Item:= TFacilityTreeItem.Create; ... end;

Para acceder a sus campos, debe declarar propiedades en IFacilityTreeItem Interface, con Getters y Setters.


TInterfacedObject en sí mismo no es referencia contada, solo son interfaces. Puede implementar interfaces utilizando TInterfacedObject, que básicamente le ahorra el esfuerzo de implementar los métodos de conteo de referencias usted mismo. Desafortunadamente, todavía no funcionará en su caso: el compilador no sabe que está asignando interfaces a la propiedad TTreeNode.Data, ya que no está declarado como una interfaz sino como un puntero. Entonces todo tipo de cosas extrañas sucederán

MyInt := TFacilityTreeItem.Create; // ref count = 1 // Node.Data := MyInt; // won''t compile Node.Data := pointer(MyInt); // no interface assignment, ref count stays 1 ... end; // ref count reaches 0, your object gets freed

Tan pronto como intente acceder a su objeto a través de la propiedad .Data, obtendrá una infracción de acceso.

Entonces, no se moleste con las interfaces en este caso, podría hacer que funcione, pero será mucho más esfuerzo de lo que vale.


Como dijo dummzeuch , puede hacer que esto funcione con las interfaces, pero requiere más código ya que la propiedad Data de un TTreeNode es un puntero. Para cualquiera que se pregunte cómo hacerlo, este enlace tiene un ejemplo de cómo hacerlo para TListItem (es prácticamente lo mismo para TTreeNode). También puede resultarle útil leer la sección sobre interfaces y la sección siguiente sobre el recuento de referencias en esa página.