close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 15 years ago

Closed 15 years ago

#869 closed defect (fixed)

Error working with Object References and Decompilation

Reported by: pgea@… Owned by: Víctor de Buen Remiro
Priority: high Milestone: OOP Implementation
Component: OOP Version: 2.0.1
Severity: critical Keywords:
Cc:

Description

He encontrado un error al trabajar con objetos.
Hasta donde he conseguido aislarlo parece que se trata de algo relacionado con la creación de nuevas referencias de un objeto, la decompilación y el _this.

El error que queda en el log es el siguiente:

ERROR: [1] SIGNAL: Abnormal termination, such as instigated by the abort function. (Abort.)

ERROR: [2] Un error inesperado ha hecho TOL inestable y la sesión debe ser cerrada

El ejercicio para reproducir esto consiste en:

  1. Crear una referencia de un objeto pidiéndoselo al método de un objeto contenedor.
  2. Decompilar esta referenca
  3. Volver a llamar a éste objeto accediendo a un método que use la referencia interna _this.

Adjunto un archivo de ejemplo.

Attachments (2)

ticket_18.ObjectReferencesAndDecompilation.tol (1.1 KB) - added by pgea@… 15 years ago.
ticket_18B.ObjectReferencesAndDecompilation.tol (1.1 KB) - added by pgea@… 15 years ago.

Download all attachments as: .zip

Change History (10)

Changed 15 years ago by pgea@…

comment:1 Changed 15 years ago by Víctor de Buen Remiro

Status: newaccepted

He reproducido el error pero sólo consigo hacerlo en modo "release". En modo "debug" sin embargo no se cae, sino que da da este error, aunque al menos apunta en la misma dirección que comentas

ERROR: [1] _this no es un objeto valido para el tipo Anything.

[Call stack]
  [1] Anything algo::GetThis (Real void)

Warning: [1] La función :: ha fallado en : 
Container::GetElement(1)::GetThis(?)

ERROR: [2] ea no se pudo crear.

comment:2 Changed 15 years ago by Víctor de Buen Remiro

Si en lugar de usar la sintaxis implícita de instancia temporal sin nombre <function>(...) :: ... como haces en

  Anything ea = Container::GetElement(1)::GetThis(?);

se crea primero la instancia explícita con nombre y luego se usa

  @Element container = Container::GetElement(1);
  Anything ea = container::GetThis(?);

entonces todo va bien.

Yo estoy pensando ya muy seriamente en prohibir directamente esa sintaxis implícita porque realmente no aporta nada importante y da muchísimos problemas.

A lo único que ayuda es a escribir un poco menos, pero la escritura física no supone ni el 1% del trabajo de programación.

A mí me resulta mucho más clara la sintaxis explícita que la implícita que de hecho no uso jamás y me va muy bien.

En cualquier caso intentaré ver qué puede estar ocurriendo pero tiene muy mal aspecto todo este asunto.

comment:3 Changed 15 years ago by pgea@…

Realmente si todos los problemas vienen de concatenar varias llamadas con :: podemos evitarlas y ya está.
Lo que me preocupa es que sea otro problema que se detecta así y que podría surgir de otro modo también.

Para mí estas llamadas son algo parecido a cuando componemos funciones y lo hago con esa misma naturalidad.
Por ejemplo, no hago:

Serie aux1 = CalInd(C,C);
Serie serie = SubSer(aux1, y2009, y2010);

sino simplemente:

Serie serie = SubSer(CalInd(C,C), y2009, y2010);

Si en lugar de métodos fuesen funciones que devuelven objetos, ¿ocurriría lo mismo?
Me refiero a algo como:

Anything ea = ObtainThis(ObtainElement(Container));

en lugar de:

Anything ea = Container::GetElement(1)::GetThis(?);

Quizá el cambio en los erorres de este tique puede deberse en parte a la solución del tique: #872

Te comento un poco de dónde surge el asunto de concatenar llamadas a métodos.
En MMS se planteó en su momento encapsular los atributos de modo que todo el acceso a los atributos se hiciera por métodos, y así poder tratar los eventos procedentes del cambio de un atributo o incluso cambios en la definición de los atributos sin que afectase al uso de los objetos.
En esas circunstancias lo que sería el acceso natural:

Text objeto1::objeto2::nombre

se vuelve:

Text objeto1::GetObjeto2(?)::GetNombre(?)

También en este sentido, se nos planteó crear múltiples métodos como:

Text objeto1::GetNombreDelObjeto2(?)

pero nos parecía más cómodo concatenar las llamadas a los métodos.
O incluso en el caso de objetos que contienen objetos hacer llamadas del tipo:

@parametro par = modelo::GetOutput("output")::GetTérmino("término")::GetParametro("grado0");

parecía más cómodo que crear los métodos intermedios con distintos tipos de argumentos como:

@parametro par = modelo::GetParameter("output","término","grado0");

o:

@parametro par = output::GetParameter("término","grado0");
@parametro par = termino::GetParameter("grado0");

o hacer todas las llamadas:

@output output = modelo::GetOutput("output");
@termino termino = output::GetTérmino("término");
@parametro par = termino::GetParametro("grado0");

comment:4 Changed 15 years ago by pgea@…

Severity: majorcritical

Respondiendo al segundo comentario sobre la propuesta de que evitando la concatenación de varias llamadas :: con:

  @Element element = Container::GetElement(1);
  Anything ea = element ::GetThis(?);

no falla.

Creo que no es del todo cierto. Puedo reproducir el mismo error u otro similar sin usar la concatenación de varias llamadas ::.
He creado un método GetElementThis que permite ver esto.

Adjunto un archivo con el ejemplo ("ticket_18B....tol").

Sigo sin tener claro qué ocurre, pero lo que parece es que cuando se decompila en determinadas circunstancia la referencia de un objeto, el _this sigue apuntando a ésta o cambia a otra referencia que ya desapareció.

comment:5 Changed 15 years ago by Víctor de Buen Remiro

A mí eso me funciona bien siguiendo los pasos que se indican.
Voy a ver si tengo cambios sin subir al SVN y ya de paso a ver si actualizo la release binaria que hace ya tiempo que le toca.

comment:6 Changed 15 years ago by Víctor de Buen Remiro

Ya he conseguido reproducirlo. No me había fijado muy bien en el comentario y el segundo paso de compilación y decompilación lo hacía en el Eval y de esa forma misteriosamente no se cae en el tercer paso

//////////////////////////////////////////////////////////////////////////////
// Compílese esta línea (con F9) y decompílese (con F8)

@Element algo = Container::GetElement(1);

A depurar tocan

comment:7 Changed 15 years ago by Víctor de Buen Remiro

En modo de depuración no se cae pero me da este error

ERROR: [1] _this no es un objeto valido para el tipo Anything.

[Call stack]
  [2] Anything algo::GetThis (Real void)
  [1] Anything Container::GetElementThis (Real index)

Warning: [1] La función :: ha fallado en : 
element::GetThis(?)

Warning: [2] La función :: ha fallado en : 
Container::GetElementThis(1)

ERROR: [2] ea no se pudo crear.

Por lo que estoy viendo el objeto algo ha sido destruido y por eso falla. El problema viene de la dualidad del objeto interno C++ BNameBlock que es el que gestiona todas las capacidades semánticas, y el objeto sintáctico BUserNameBlock que es el objeto TOL visible. El BNameBlock es el que se reconoce a sí mismo por la cláusula _this} pero no puede devolverse a sí mismo porque no es un objeto TOL, así que devuelve el puntero owner_ del objeto TOL. En este caso debería ser el objeto local element para el que fue creado y que está aún vivo en el Set Container::_.elements, pero durante la asignación al objeto global algo éste de adueñó del owner_ y como en este caso ya no existe es una referencia inválida que lo mismo puede hacer que se dé un error o que se caiga TOL.
Voy a ver cómo puedo arreglar esto sin que afecte a la mecánica de asignación del owner_ que precisamente sigue esa estrategia de reasignación en la esperanza de que los objetos globales suelen durar más que los locales.
A parte de eso creo que puede haber algún problema en el conteo de referencias que aún no tengo controlado, pero eso es otra historia.

comment:8 Changed 15 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: acceptedclosed

El problema ha sido resuelto finalmente eliminando la reasignación del owner_ puesto que se trata de algo que en realidad se hizo con la intención de que en el inspector de objetos de TOLBase se viera el FullName, lo cual fue desechado finalmente.

Note: See TracTickets for help on using tickets.