Opened 15 years ago
Closed 15 years ago
#863 closed defect (remind)
Object decompilation, when a object contains a reference to itself
Reported by: | Owned by: | Víctor de Buen Remiro | |
---|---|---|---|
Priority: | normal | Milestone: | OOP Implementation |
Component: | OOP | Version: | |
Severity: | major | Keywords: | |
Cc: |
Description
El problema surge a la hora de gestionar objetos que contienen otros objetos y se desea que un objeto contenido conozca al objeto que lo contiene.
Para motivar esto podemos considerar una situación interesante que surge cuando se almacenan estructuras similares a grafos. Veamos un ejemplo:
Imaginemos una clase grafo (@Graph
) que contiene un conjunto de vértices (@Vertex
) y otro de aristas (@Edge
). Los objetos aristas, a su vez contienen referencias a los dos vértices que unen.
Imaginemos ahora pues, que queremos desde un objeto vértice conocer todas las aristas que le apuntan. O incluso más queremos eliminarlas todas.
Parece lógico que esta acción implica la colaboración del objeto grafo.
Así si se llamara a un método del vértice GetEdges()
éste llamaría a su padre preguntándoselas: algo como parent::GetEdgesWithVertex(él_mismo)
.
O incluso: parent::RemoveEdgesWithVertex(él_mismo)
.
El problema al tratar este tipo de referencias, donde el objeto contiene objetos que lo referencian, es que los objetos no se decompilan adecuadamente.
Adjunto un ejemplo sencillo, donde si no se limpia el contenedor (método Clear
) no puede decompilarse y compilarse nuevamente.
En MMS esta cuestión se ha tratado usando direcciones de memoria (GetAddressFromObject y GetObjectFromAddress
) aunque este modo además de artificial y poco elegante dificulta la copia de los objetos y en ocasiones genera algún error debido a la desaparición de la referencia del objeto cuya dirección se apuntó.
Attachments (2)
Change History (7)
Changed 15 years ago by
Attachment: | ticket_17.ObjectDecompilation.tol added |
---|
comment:1 Changed 15 years ago by
comment:2 Changed 15 years ago by
Lo había probado pero no funciona.
En el ejemplo bastaría con añadir a @Container
el método:
Real __destroy(Real void) { Clear(?) };
Me da la impresión de que como existen dos referencias al mismo objeto algo falla.
Supongo que el primero en comenzar a destruirse es el exterior pero no lanza el __destroy
porque aún queda la copia interior que pasaría a ser la única.
Luego ya no soy capaz de comprender muy bien qué pasa, pero no se llega a destruir el objeto.
comment:3 Changed 15 years ago by
Creo que ya lo veo más claro:
Si creo un objeto A que contiene a otro objeto B que a su vez tiene una referencia a A, lo que tengo es lo siguiente: Dos objetos independientes y tres referencias.
Los objetos A y B como entes están en la memoria (objA) y (objB).
Tengo una referencia a A (refA1) que me permite acceder al objeto A (objA).
Desde éste (objA) encuentro una referencia a B (refB1) que me permite acceder
al objeto B (objB).
Desde el objeto B (objB) encuentro una referencia a A (refA2) que permite de nuevo acceder al objeto A (objA).
Cuando se decompila la referencia a A (refA1), la más exterior, el objeto no se destruye, pues aún queda otra referencia (refA2), y sólo se destruye la referencia exterior (refA1).
El problema es que los objetos quedan inaccesibles pues cada uno tiene una referencia al otro, pero ya no queda ninguna referencia útil.
El problema creo que no es nada novedoso y parece que en otros lenguajes ya han implementado un recolector de este tipo de basura. Aunque éste puede que sea algo ineficaz:
http://www.amk.ca/python/2.0/index.html#SECTION000900000000000000000
Parece entonces que la solución más sencilla pasa por evitar crear estas estructuras cíclicas, o intentar usar algún remedio que evite esta situación.
comment:4 Changed 15 years ago by
Se me ocurre una solución que permitiría evitar la existencia de referencias cíclicas por ahí sueltas que luego TOL no sabe decompilar.
Se trata de introducir una clase intermediaria que hace de interfaz a la que sufre las referencias cíclicas. Adjunto un ejemplo de cómo sería la implementación al estilo del ejemplo propuesto.
Changed 15 years ago by
Attachment: | ticket_17B.ObjectDecompilation.tol added |
---|
comment:5 Changed 15 years ago by
Resolution: | → remind |
---|---|
Status: | new → closed |
Entiendo que has encontrado una forma bastante razonable de salvar la situación por lo que en principio podemos postergar a resolución de este ticket para otro momento, si es que efectivamente es posible.
Yo creo que lo más apropiado sería definir un destructor en esa clase que llamara al método
Clear