[C con Clase] Posible BUG de GCC en llamadas a función con declaración de variable estática?

Gilberto Cuba Ricardo gilberto.cuba en ucp.ho.rimed.cu
Dom Nov 7 02:56:41 CET 2010


Hola Lista,

Realmente no sabía como ponerle en el asunto al mensaje, pero la
cuestión es que me suena bastante extraño este tipo de error. El
siguiente programa es una abstracción de una aplicación donde se está
produciendo un error en tiempo de corrida que "explota" la
aplicación y es cerrada por el sistema en el caso de Windows, porque
se queda mareada.

El programa compila bien en todos los casos con MS Visual Studio 2005,
2008, 2010, MinGW 4.5.1 sobre Windows 7 y en GCC de Debian 4.3. Sin
embargo, da errores de ejecución cuando es compilado y ejecutado con
MinGW y GCC. Todo apunta a un BUG de gcc como verán a continuación; o
tal vez es algún error que no logro ver.

=================== CÓDIGO ===================
  template <class T>
  class reference
    {
      public:
        reference(T& p)
        {
        }
    };

  struct schema
    {
    };

  struct opaque_schema : schema
    {
    };

  template <typename T>
  struct schema_descriptor
    {
      typedef opaque_schema type;
    };

  template <typename T>
  inline schema* type_schema()
    {
      typedef typename schema_descriptor<T>::type type_type;
      static type_type result;
      //static typename schema_descriptor<T>::type result;
      return &result;
    };

  struct composite_schema : schema
    {
      composite_schema(schema* _delgate)
        {
        }
    };

  template <typename T>
  struct reference_schema : composite_schema
    {
      reference_schema():
        composite_schema(type_schema<T>())
        {
        }
    };

  struct basic_schema : schema
    {
      public:
        template <typename S, typename D, typename C>
        void caster()
          {
            schema *src = type_schema<S>();
          }
    };

  template<typename T>
  struct object_schema : basic_schema
    {
      template <typename I>
      void implements()
        {
          typedef reference<T> my_ref;
          typedef reference<I> their_ref;

          caster<my_ref, their_ref, int>();
        }
    };

  template <typename T>
  struct pointer_schema : composite_schema
    {
      pointer_schema():
        composite_schema(type_schema<T>())
        {
        }
    };

  template <typename T>
  struct dynamic_object_schema : object_schema<T>
    {
      dynamic_object_schema()
        {
          this->template implements<int>();
        }
    };

  template <typename T>
  class editable_object
    {
    };

  class sponge_object : public editable_object<sponge_object>
    {
    };

  struct sponge_object_schema : dynamic_object_schema<sponge_object>
    {
    };

  template <>
  struct schema_descriptor<sponge_object>
    {
      typedef sponge_object_schema type;
    };

  template <>
  struct schema_descriptor< reference<sponge_object> >
    {
      typedef reference_schema<sponge_object> type;
    };

int main()
  {
    reference_schema <sponge_object> exploit;

    return 0;
  }
=================== CÓDIGO ===================

Empecé a entrar con el debuguer y este es el resultado que fui
siguiendo y el que más se acercaba a la pila del gdb de Linux y más
aún cuando lo corrí con el debuguer de vs2010.

1 - reference_schema <sponge_object>

    // está especializado el que viene
2   - type_schema <sponge_object>

3     - sponge_object_schema

4       - dynamic_object_schema <sponge_object>

5         - object_schema <sponge_object>::implements <IDynamicObject>();

6           - basic_schema::caster <reference<sponge_object>, reference<IDynamicObject>, ...>();

              // está especializado el que viene y da paso a la recursividad que lo hace explotar
7             - type_schema < reference <sponge_object> >

                // a partir de aquí empieza a repetirse
8               - reference_schema <sponge_object>

                  // explota aquí tanto en windows como en linux con el gdb porque al parecer
                  // detecta ya la recursión que cae en un ciclo que no tiene forma de parar
9                 - type_schema <sponge_object>

Como verán 1 y 8 son iguales y luego 2 y 9 igual también. Pero el
hecho es que como es una declaración estática dentro de 'type_schema'

      static type_type result;

no tiene por qué volver a crear ese objeto, ya que fue creado con
anterioridad en el paso 2, y lo que debería de hacer es tomar su valor
y devolverlo; sin embargo, como pudieran apreciar los que lo ejecuten,
verán el problema durante la ejecución en una compilación con gcc.
Sobre GNU Debian Linux me da el error:

terminate called after throwing an instance of
'--gnu_css::recursive_init_error' what : std::exceptions.

y sobre Windows se da una mareada grande hasta que se cierra la aplicación.

-- 
Saludos,
 Gilberto Cuba Ricardo

PD: Disculpen por lo extenso del mensaje, pero necesitaba dar
argumentos.





Más información sobre la lista de distribución Cconclase