Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Fucniones C ( Arranque, Parada )

Iniciado por Degiik, 21 de Mayo de 2006, 10:59:58 AM

« anterior - próximo »

zupervaca

 
Citara.- No me llames majete
Vale, pero es una simple forma de hablar

Citarb.- Que difencia hay entre una clase global, i una clase estatica global ?
El orden de destruccion, veo que no te has empollado el estandar c++, una clase global no estatica se destruye antes que una clase estatica global.

No se por que preguntas para luego hacer estas cosas.

Degiik

Cita de: "zupervaca"
Citara.- No me llames majete
Vale, pero es una simple forma de hablar

Citarb.- Que difencia hay entre una clase global, i una clase estatica global ?
El orden de destruccion, veo que no te has empollado el estandar c++, una clase global no estatica se destruye antes que una clase estatica global.

No se por que preguntas para luego hacer estas cosas.
CitarEl orden de destruccion, veo que no te has empollado el estandar c++, una clase global no estatica se destruye antes que una clase estatica global

#include <windows.h>
#include <stdio.h>

class a
{
public:
 int v;
 
 a(){v=0;}
 ~a()
  {
  char s[10];
 
  sprintf (s,"%d",v);
  MessageBox (NULL,s,NULL,MB_OK);
  }
};

static class b
{
public:
 int v;
 
 b(){v=1;}
 ~b()
  {
  char s[10];
 
  sprintf (s,"%d",v);
  MessageBox (NULL,s,NULL,MB_OK);
  }
};

class c
{
public:
 int v;
 
 c(){v=2;}
 ~c()
  {
  char s[10];
 
  sprintf (s,"%d",v);
  MessageBox (NULL,s,NULL,MB_OK);
  }
};

a aa;
b bb;
c cc;

void main (void)
{


}


Salida:

2
1
0


CitarNo se por que preguntas para luego hacer estas cosas.

Pregunto porque no se si eres muy bueno, o muy malo. En cualquier caso, tu tono es muy prepotente y sentenciador, y no queria realizar un asociación directa entre lo primero y segundo.
egiik: h-O-5 hoja/ingestión 100mo Vida suspendida ( 1 día )

zupervaca

 
CitarPregunto porque no se si eres muy bueno, o muy malo. En cualquier caso, tu tono es muy prepotente y sentenciador, y no queria realizar un asociación directa entre lo primero y segundo
Es normal que te parezca todo eso si despues de decirte las cosas te ries de mi, lo importante es que te funciona como has podido comprobar.

http://arco.inf-cr.uclm.es/~dvilla/pensar_...++/ch10s01.html
En concreto: "1.1.2. Destructores de objetos estáticos"

hotcamus

 Umm, creo que aqu� se est�n mezclando conceptos:

CitarSi hablas de objetos me imagino que usaras c++, entonces lo que puedes hacer es crear una clase estatica global

Supongo que te refieres a una instancia est�tica de una clase (por el ejemplo que hay posteriormente). Que yo sepa, no existe el concepto de clase est�tica.

CitarNo es paranoia es todos los compiladores se comportan de la misma manera ya que es un estandar la forma de creacion y destruccion de objetos

El est�ndar define el orden de destrucci�n de objetos no est�ticos. Para objetos globales (o atributos estáticos), no se puede asegurar el orden en el que se destruyen (depende del compilador). En cambio, para objetos est�ticos locales (aquellos definidos dentro de una funci�n), este orden s� est� garantizado.

Citar...una clase global no estatica se destruye antes que una clase estatica global.

De nuevo, suponiendo que hablas de instancias, una variable global es estática, ¿o no?. Si a una variable declarada en el ámbito global se le añade el modificador static entonces pasa a ser "privada" de la unidad de compilación y no tiene que ver con su almacenamiento.

Citarstatic class b
{
public:
int v;

b(){v=1;}
~b()
  {
  char s[10];

  sprintf (s,"%d",v);
  MessageBox (NULL,s,NULL,MB_OK);
  }
};

"static class" ??? Esto no existe. El ejemplo funciona porque los objetos que creas (aa, bb y cc) no son est�ticos, por lo que se destruyen en el orden inverso en el que est�n declarados. El VS2003 genera este mensaje:


Citarwarning C4091: 'static ' : ignored on left of 'b' when no variable is declared

En definitiva, haciendo uso �nicamente de C++ si tienes objetos est�ticos globales, por ejemplo, con alg�n singleton, no existe ese punto a ejecutar despu�s de todos los destructores de los objetos. Tendr�s que recurrir a alguna funci�n de CRT.

zupervaca

 Efectivamente me refiero a una instancia, no me habia fijado que el habia puesto "static class b"

En la web que he puesto y en el apartado que indique habla sobre el orden de destruccion de objetos:
CitarComo la destrucción ordinaria, la destrucción de objetos estáticos se lleva a cabo en orden inverso al de la inicialización. Hay que tener en cuenta que sólo los objetos que han sido construidos serán destruidos. Afortunadamente, las herramientas de desarrollo de C++ mantienen un registro del orden de inicialización y de los objetos que han sido construidos
En todos los compiladores que he usado funciona igual, el primero en crearse es el ultimo en destruirse por que usan una pila o simplemente guardan el orden como indica el quote, no obstante si quieres asegurarte al 100% de que se inicialicen en el orden correcto, para asi, que su destruccion sea en el orden correcto se suele hace el truco de hacer una funcion estatica global por cada clase, que sera llamada por ejemplo desde el main, asi de esta manera indicaras el orden de creacion de los objetos.  

hotcamus

 El libro de Stroustrup dice que eso sólo se garantiza para objetos estáticos locales (definidos dentro de una función). Ahora bien, para objetos estáticos globales o atributos estáticos de una clase, eso no está garantizado, especialmente, cuando los objetos globales se definen en varias unidades de compilación.

No tengo el estándar pero recuerdo que la implementacón típica del patrón Singleton sufre este problema. Por ello hay publicada una "gem" que se basa en una template y algo de aritmética de punteros. Podría buscar el enlace si es necesario.

Ahora bien, si como dices funciona bien en los compiladores que has probado, pues nada, pero creo que no habría que "fiarse" de eso.

Flint

 
Cita de: "hotcamus"No tengo el estándar pero recuerdo que la implementacón típica del patrón Singleton sufre este problema. Por ello hay publicada una "gem" que se basa en una template y algo de aritmética de punteros. Podría buscar el enlace si es necesario.

Así es, pero el hack que utiliza el autor en dicha gem no es portable:


// ...
static T* m_Singleton;
// ...

// Dentro del constructor...
int offset = (int)(T*)1 - (int)(Singleton *)(T*)1;
m_Singleton = (T*)((int)this + offset);

// ...


El código del constructor asume que el tamaño de un puntero es el mismo que el de un int, lo cual no está asegurado en C++, y además no almacena información adicional necesaria para representar los punteros (y con ello asegurar un correcto comportamiento multiplataforma). Con un static_cast el asunto se soluciona y el código se vuelve de pronto portable, más agradable de leer y más fácil de entender.  :)

zupervaca

 Yo la solucion que hago si quiero que los objetos se inicialicen en un orden concreto usando el singleton es esto:
#include <stdio.h>

template <class TYPE> class Singleton
{
public:
TYPE *operator -> ()
{
 return &this->object;
}

static TYPE object;
};
template <class TYPE> TYPE Singleton<TYPE>::object;

class a
{
public:
a()
{
 fprintf( stderr, "Constructor de A\r\n" );
}

~a()
{
 fprintf( stderr, "Destructor de A\r\n" );
}

void hola()
{
}
};

class b
{
public:
b()
{
 fprintf( stderr, "Constructor de B\r\n" );
}

~b()
{
 fprintf( stderr, "Destructor de B\r\n" );
}

void hola()
{
}
};

int main ()
{
Singleton<a> aa;
Singleton<b> bb;

aa->hola();
bb->hola();

return 0;
}

Cambiando el orden dentro del main de "Singleton aa;" y "Singleton bb;" inicializaremos uno u otro antes, de esta manera incluso en aplicaciones multihilo se crea una sola instancia de una clase y en el orden correcto para su inicializacion y destruccion, se sobre entiende que los multiples hilos del app se crean despues de indicar todos los singletons

hotcamus

 Pues por lo que yo entiendo, en este ejemplo precisamente no est� garantizado el orden de inicializaci�n ya que las variables est�ticas son miembros de la clase.

Si cambiases el atributo est�tico a una variable local s� que estar�a garantizado:


TYPE *operator -> ()
{
static TYPE object;
return &object;
}


En este caso, las dos llamadas que tienes en el main determinar�an el orden de construcci�n y, por lo tanto, el de destrucci�n.

zupervaca

 Buff ¿por que no pruebas el ejemplo en todos los compiladores que quieras y lo dejamos? es que creo que es perder el tiempo intentar demostrar algo que funciona en el 100% de los casos y de los compiladores, es que seria lo de siempre, pondria mil links, tu pondrias otros y estariamos en un sin acabar.

Jare

Cita de: "zupervaca"Buff ¿por que no pruebas el ejemplo en todos los compiladores que quieras y lo dejamos? es que creo que es perder el tiempo intentar demostrar algo que funciona en el 100% de los casos y de los compiladores, es que seria lo de siempre, pondria mil links, tu pondrias otros y estariamos en un sin acabar.
Solo por que te funcione no significa que este bien hecho.

zupervaca

 
Cita de: "Jare"
Cita de: "zupervaca"Buff ¿por que no pruebas el ejemplo en todos los compiladores que quieras y lo dejamos? es que creo que es perder el tiempo intentar demostrar algo que funciona en el 100% de los casos y de los compiladores, es que seria lo de siempre, pondria mil links, tu pondrias otros y estariamos en un sin acabar.
Solo por que te funcione no significa que este bien hecho.
Por lo mismo que por que no se sepa por que funciona no significa que este mal hecho.

El por que funciona es simple, la clase singleton alberga un miembro estatico, pero la instancia de la clase en si no es estatica por lo que al indicarlas en la funcion main se asignan como memoria automatica, es decir, en la pila, y la pila tiene un orden muy estricto, el primero en destruirse es el ultimo en crearse, y ya que el estandar c++ indica que las instancias de las clases solo se inicializan cuando son llamadas por primera vez el orden se vuelve correcto, no hay mas, ahora si sigueis sin entenderlo abandono por que ya cansa tener que explicar las cosas.

Jare

 
Cita de: "zupervaca"Por lo mismo que por que no se sepa por que funciona no significa que este mal hecho.
Cuando el autor no sabe explicar por qué funciona, tampoco puede GARANTIZAR que vaya a seguir funcionando mañana, y por tanto su trabajo no está bien hecho (a no ser que te paguen por hacer algo y solo te exijan que funcione "hoy" ;)). Y, como vamos a ver más abajo, cuando la razon por la que funciona es "implementation dependent" o "por pura casualidad", entonces ESTA mal hecho, sepas o no sepas por qué.
Cita de: "zupervaca"El por que funciona es simple, la clase singleton alberga un miembro estatico, pero la instancia de la clase en si no es estatica por lo que al indicarlas en la funcion main se asignan como memoria automatica, es decir, en la pila, y la pila tiene un orden muy estricto, el primero en destruirse es el ultimo en crearse, y ya que el estandar c++ indica que las instancias de las clases solo se inicializan cuando son llamadas por primera vez el orden se vuelve correcto
Ni de coña.

"For the static member to exist, it is not necessary that any objects of the class type exist"

Las variables estáticas de una funcion son inicializadas la primera vez que se ejecuta la función, ni antes ni despues. Para las estáticas de clase eso no es aplicable, porque ni siquiera hace falta que exista una instancia de la clase para que la estática de esa clase exista.

"Initialization of global static objects in a translation unit. This may occur either before entry to main or before the first use of any function or object in the object's translation unit."

Las variables estáticas de una clase se pueden inicializar mucho antes y en un orden no definido por el estándar. Lo curioso es que los templates en general ni siquiera viven en una translation unit concreta, sino (generalmente) como multiples en una amalgama de "translation units" en las que se usa ese template, y que el linker se ocupa de fundir en una sola copia.

La presencia de las instancias en la pila no tiene NADA que ver. La realidad? Funciona en tu ejemplo solamente por la forma en que el compilador / linker generan el código asociado al template en ese caso concreto. Tu ejemplo es tremendamente fácil de destrozar:

#include <stdio.h>

template <class TYPE> class Singleton
{
 static TYPE object;
public:
 TYPE *operator -> () { return &this->object; }
};
template <class TYPE> TYPE Singleton<TYPE>::object;

struct A { A() { puts("A::A()"); } ~A() { puts("A::~A()"); } void f() {puts("A::f()"); } };
struct B { B() { puts("B::B()"); } ~B() { puts("B::~B()"); } void f() {puts("B::f()"); } };

void f()
{
 Singleton<B> b;
 puts("f()");
 b->f();
}

int main()
{
 Singleton<A> a;
 Singleton<B> b;

 a->f();
 b->f();

 f();
 return 0;
}

Y la salida de ese programa es:

B::B()
A::A()
A::f()
B::f()
f()
B::f()
A::~A()
B::~B()

Como puedes ver, el orden de los singletons en main() es A y luego B, sin embargo las llamadas a los constructores de esas clases ocurren en orden inverso. Por qué? Porque lo que dices simplemente NO ES CIERTO, aunque en determinados casos funcione por casualidad. Mejor dejarse de filigranas que ni funcionan ni responden a una regla establecida y estandarizada. Globales con inicialización explícita y a vivir que son dos días.

PD: Joer que destrozo hace el foro con los acentos y tal. :(







Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.