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 13 years ago

Closed 13 years ago

#1478 closed defect (fixed)

Corrupted method: segmentation fault

Reported by: Jorge Owned by: Jorge
Priority: highest Milestone: Mantainance
Component: Kernel Version: 3.1
Severity: blocker Keywords:
Cc:

Description

The following code give rise segmentation fault within tol:

#Require GuiTools;

Real RealSquare( Real x, Set args )
{
  Real sqX = x*x;
  WriteLn( "El cuadrado de " << x << " es " << sqX );
  sqX
};

Real GuiTools::MenuManager::defineMenuCommand
( "Real",
  [[ Text name = "Real_SQ",
     Text label = "Cuadrado del Real",
     Real flagGroup = 0,
     Code CmdInvoke = RealSquare ]]
);

Real a = 1;

GuiTools::MenuManager::invokeEntry( "Real_SQ", [[ a ]] );

the error is:

<E>
ERROR: [1] Corrupted method RealSquare
Possibly this problem is due to a non standard use of OOP, if this function was assigned to a member of type Code of a NameBlock or Class instance that has been destroyed already.</E>
[Call stack]
Segmentation fault

I will try to isolate it from GuiTools.

Change History (17)

comment:1 Changed 13 years ago by Jorge

valgrind output is:

==15625== 
==15625== Invalid read of size 4
==15625==    at 0x5A0D6F0: BNameBlock::EnsureIsAssigned() const (nameblock.cpp:303)
==15625==    by 0x5A4DAED: BSyntaxObject::FullName() const (syn.cpp:421)
==15625==    by 0x5A21A47: BUserFunction::FullName() const (oprimp.cpp:1521)
==15625==    by 0x59CA0C5: BUserFunction::ShowCallStack() (opr.cpp:973)
==15625==    by 0x5868C92: Error(BText const&) (out.cpp:455)
=

comment:2 Changed 13 years ago by Jorge

The following code reproduce the error message but not the segmentation fault:

Class @A {
  Set _.commands = Copy( Empty );
  Real Invoke( Real x )
  {
    Code action = _.getCode( ? );
    action( x )
  };

  Code _.getCode( Real void )
  {
    _.commands::CmdInvoke
  };
  
  Static @A New( NameBlock args )
    {
      @A n = [[ Set _.commands = [[ Code CmdInvoke = args::CmdInvoke ]] ]]
    }
};

Real SQ_Real( Real x )
{
  Real x * x
};

@A opt = @A::New( [[ Code CmdInvoke = SQ_Real ]] );

Real opt::Invoke( 2 );

comment:3 Changed 13 years ago by Jorge

This is even a smaller piece of code:

Real SetAA( NameBlock args )
{
  Real 1
};

Real SQ_Real( Real x )
{
  Real x * x
};

Real SetAA( [[ Code CMD = SQ_Real ]] );

Real SQ_Real( 1 );

comment:4 Changed 13 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: newclosed

(In [4341]) Fixes #1478
If BUserCode has different Name or Level than BOperator, it can't be a method

comment:5 Changed 13 years ago by Jorge

(In [4342]) refs #1478, regressive test

comment:6 Changed 13 years ago by Pedro Gea

El problema con los Code es el mismo que con los TimeSet, (véanse #1451, #1470 y #1471) por el empeño de no gestionar los objetos mediante referencias (véase #1431) sino a través de nuevos objetos que se apoyan en otros existentes previos.

Compárense los dos ejemplos siguientes:

Real fun1(Real x) { x*x };
NameBlock m = {
  NameBlock n1 = [[
    Code fun2 = fun1
  ]];
  NameBlock n2 = [[
    Code fun = n1::fun2
  ]]
};
Real m::fun(1);

que a pesar de funcionar da el error:

ERROR: [1] Corrupted method fun1
Possibly this problem is due to a non standard use of OOP, if this function was assigned to a member of type Code of a NameBlock or Class instance that has been destroyed already.

y (válido para v3.1 en adelante):

Real fun1(Real x) { x*x };
NameBlock m = {
  NameBlock n1 = [[
    @Code fun2 = @Code(fun1)
  ]];
  NameBlock n2 = [[
    @Code fun = @Code($(n1::fun2))
  ]]
};
Real {
  @Code aux = m::fun;
  $aux(1)
};

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

Partamos de la base de que aquí nadie se empeña en nada, porque eso es faltar al respeto y dudar de la profesionalidad de los desarrolladores de TOL.

Con todos mis respetos debo decirte que estás mezclando churras con meninas, pues no tiene nada que ver una cosa con la otra y además no se puede pretender que los objetos sean a la vez referencias.

Para empezar no tenemos punteros ni referencias como en C u otros lenguajes porque para eso hubiéramos hecho todo en C++ desde el principio y que lo aprendiera todo el mundo y a ver a dónde hubiéramos llegado.

Pero en cualquier caso es tautológicamente imposible que un objeto sea una referencia de otro del mismo tipo. Un objeto puede contener una referencia pero no puede serlo. Los lenguajes que admiten punteros y referencias lo hacen como tipos distintos nominados mediante prefijos u operadores.

Los conjuntos son la única forma de gestionar los objetos como referencias en TOL y no puede haber ninguna otra. En particular los @<type> son más prácticos y elegantes pero no dejan de ser un Set.

Este error se debe a que en el momento de la creación de un NameBlock resulta terriblemente complicado distinguir un miembro Code de un método. Sólo es posible aplicar reglas heurísticas y con las últimas añadidas se resuelve el problema.

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

(In [4353]) Refs #1478
Removing traces

comment:9 Changed 13 years ago by Víctor de Buen Remiro

(In [4354]) Fixes #1478 in 3.1

comment:10 Changed 13 years ago by Jorge

(In [4361]) refs #1478, los campos CmdInvoke y CmdCheckState se pueden pasar como Code o @Code.

comment:11 Changed 13 years ago by Jorge

Resolution: fixed
Status: closedreopened

El siguiente código, todavía genera una caída en TOL (solo en linux)

#Require GuiTools;

Real {
  Real RealSquare( Real x, Set args )
  {
    Real sqX = x*x;
    WriteLn( "El cuadrado de " << x << " es " << sqX );
    sqX
  };
  
  // con esto se genera el segmentation fault 
  NameBlock auxiliar = [[
    Code RealSquare
  ]];
  
  Real GuiTools::MenuManager::defineMenuCommand("Real", 
    [[ Text name = "Real_SQ",
       Text label = "Cuadrado del Real",
       Real flagGroup = 0,
       Code CmdInvoke = RealSquare ]])
};

Real GuiTools::MenuManager::invokeEntry( "Real_SQ", [[ 3 ]] );

genera la salida ya vista en el enunciado del ticket:

<E>
ERROR: [1] Corrupted method RealSquare
Possibly this problem is due to a non standard use of OOP, if this function was assigned to a member of type Code of a NameBlock or Class instance that has been destroyed already.</E>
[Call stack]
Segmentation fault

prestar atención al mensaje de Segmentation fault emitido justo en el momento de sacar la traza del error.

Un código parecido pero que si logra a sacar la traza del stack es este:

#Require GuiTools;

Real {
  Real F1( Real x, Set args )
  {
    WriteLn( "Ejecutando F1 " << x );
    Real 1
  };

  // para fastidiar
  NameBlock auxiliar = [[
    Code F1
  ]];
  
  Real GuiTools::MenuManager::defineMenuCommand("Real", 
    [[ Text name = "MnuF1",
       Text label = "Solo F1",
       Code CmdInvoke = F1 ]])
};

Real GuiTools::MenuManager::invokeEntry( "MnuF1", [[ 3 ]] );

genera la traza siguiente:

<E>
ERROR: [1] Corrupted method F1
Possibly this problem is due to a non standard use of OOP, if this function was assigned to a member of type Code of a NameBlock or Class instance that has been destroyed already.</E>
[Call stack]
[3] Real F1 (Real x, Set args)
[2] Real option::option::inst::invoke (Anything objOrSelection)
[1] Real GuiTools::MenuManager::invokeEntry (Text optionName, Set objOrSelection)
Ejecutando F1 3

comment:12 Changed 13 years ago by Jorge

Owner: changed from Víctor de Buen Remiro to Jorge
Status: reopenedaccepted

comment:13 Changed 13 years ago by Jorge

(In [4370]), al limpiar un NameBlock se debe establecer a NULL el NameBlock del BOperator si este comparte el NameBlock con el miembro Code que lo referencia.

comment:14 Changed 13 years ago by Jorge

(In [4372]) refs #1478, more check on the test

comment:15 Changed 13 years ago by Jorge

(In [4373]) refs #1478, porting test to branch 3.1

comment:16 Changed 13 years ago by Jorge

(In [4375]) refs #1478, porting [4370] from trunk.

comment:17 Changed 13 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: acceptedclosed
Note: See TracTickets for help on using tickets.