Pregunta

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 & amp; había asumido que debido a que son contados por referencia, no debería necesitar liberarlos. eso sería útil.

sin embargo, al verificar esto, activé ReportMemoryLeaksOnShutdown y descubrí que no están siendo liberados después de todo.

estos objetos se crean en un marco que se coloca en el formulario principal. en el FormClose del formulario principal, borro los nodos del árbol de modo que cada objeto deba liberarse.

¿qué está pasando?

¡gracias por tu ayuda!

¿Fue útil?

Solución

TInterfacedObject en sí mismo no cuenta con referencia, solo las interfaces sí. Puede implementar interfaces utilizando TInterfacedObject que básicamente le ahorra el esfuerzo de implementar los métodos de conteo de referencia 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 se declara como una interfaz sino como un puntero. Entonces sucederán todo tipo de cosas raras:

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 te molestes con las interfaces en este caso, podrías hacer que funcione, pero será mucho más esfuerzo de lo que vale.

Otros consejos

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 la interfaz IFacilityTreeItem, con Getters y Setters.

Como dummzeuch dijo , puede obtener esto funciona con interfaces, pero requiere algo más de 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 casi lo mismo para TTreeNode). También puede resultarle útil leer la sección sobre interfaces y posteriores sección sobre el recuento de referencias en esa página.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top