• Sábado 9 de Noviembre de 2024, 03:26

Autor Tema:  Extraño comportamiento de destructor  (Leído 1061 veces)

killrazor

  • Miembro activo
  • **
  • Mensajes: 44
    • Ver Perfil
Extraño comportamiento de destructor
« en: Domingo 11 de Octubre de 2009, 17:26 »
0
Hola a todos.
Estoy haciendo una clase que usa un Log para guardar mensajes. Lo
extraño es que tal como se crea la clase, automaticamente se llama al
destructor. El codigo del main es este:

Código: C++
  1. int main(int argc, const char* argv[]){
  2.        //Aqui creo un logger
  3.        CGeneralLogger glogger =
  4. CGeneralLogger("Log333.txt",tools::GLog::LOGLEVEL_DEGUG);
  5.  
  6.        // Aqui recojo una instancia del singleton GlobalLogger
  7.        tools::GLog::CGlobalLog *gLog;
  8.        gLog = tools::GLog::CGlobalLog::getInstance();
  9.        gLog->setMinimumLogLevel(tools::GLog::LOGLEVEL_DEGUG);
  10.  
  11.        // Aqui agrego la clase al log para que la llame en processMessage.
  12.        gLog->addListener(&glogger);
  13.        gLog->addMessage("Inicio del Log", "[GLOBAL]",tools::GLog::LOGLEVEL_DEGUG);
  14.  
  15.        //Aqui se llama a la funcion virtual para escribir los mensajes a los listeners.
  16.        gLog->processMessages();
  17.        cout << "Hola mundo" << endl;
  18.        system("PAUSE");
  19.        return EXIT_SUCCESS;
  20. }
  21.  

El del constructor es este:
Código: C++
  1.  
  2. CGeneralLogger::CGeneralLogger(std::string fileName,
  3. tools::GLog::LogLevel lvl):m_fileName(fileName), m_level(lvl)
  4. {
  5.        m_file = new std::ofstream;
  6.        m_file->open(m_fileName.c_str(), std::ios_base::out |std::ios_base::app);
  7.        tools::GLog::CGlobalLog *log;
  8.        log = tools::GLog::CGlobalLog::getInstance();
  9. }
  10.  
  11.  

Y el del destructor es este:
Código: C++
  1.  
  2. CGeneralLogger::~CGeneralLogger(void)
  3. {
  4.        *m_file << "closing file" << std::endl;
  5.        m_file->close();
  6. }
  7.  
  8.  

Y el codigo en addListener, es este:
Código: C++
  1.  
  2. void CGlobalLog::addListener( IListener* listener, std::string loggerGroup /*= "[GLOBAL]"*/ )
  3.  {
  4.      std::pair<t_ListenerVectorMap::iterator,bool> p =
  5.      listenerVectorMap.insert(std::pair<std::string,t_ListenerVector*>(loggerGroup,new t_ListenerVector()));
  6.      p.first->second->push_back(listener);
  7.  }
  8.  
  9.  

Mis sospechas son que en algun sitio de las STL que uso en addListener
provocan algun tipo de constructor por defecto que lleva a una llamada al
destructor del objeto. Ademas, una vez se acaba el main, tambien se
llama al destructor. Por otro lado, si declaro el destructor como
virtual se produce una tercera llamada al destructor.

La verdad es que ando bastante perdido. Si me podeis echar una mano os
lo agradeceria muchisimo.

r0d

  • Miembro activo
  • **
  • Mensajes: 37
  • Nacionalidad: fr
    • Ver Perfil
    • http://r0d.developpez.com/index-es.php
Re: Extraño comportamiento de destructor
« Respuesta #1 en: Lunes 12 de Octubre de 2009, 15:11 »
0
Hola,

creo que el problema puede estar en esta linea:
Código: C++
  1. CGeneralLogger glogger = CGeneralLogger("Log333.txt",tools::GLog::LOGLEVEL_DEGUG);
  2.  
Porque creo que lo que hace este codigo es:
1. crea una instancia glogger de CGeneralLogger con el constructor por defecto
2. crea un objeto temporal con los parametros dados
3. llama el operador de afectación
4. destruye el objeto temporal

Es un tema complicado, porque lo que pasa exactamente puede cambiar segun el compilador y sobre todo las opciones de compilación.

De todas formas, es mejor hacer lo siguiente:
Código: C++
  1. CGeneralLogger glogger("Log333.txt",tools::GLog::LOGLEVEL_DEGUG);
  2.  

Pero no entiendo: ¿usas CGeneralLogger en forma de Singleton?  es lo que me parece porque usas la funcion GetInstance()
Me parece raro porque:
1. Si CGeneralLogger es un singleton, no hay que instanciarlo fuera de su-mismo (es por eso que los constructores son declarados en privado en el pattern Singleton)
2. CGeneralLogger parece dedicada a tener herencia (hablas de la funcion virtual processMessage, supongo que es un patrono Template Method y que tendras hijos de CGeneralLogger que implementan processMessage de maneras distintas ¿no?)

killrazor

  • Miembro activo
  • **
  • Mensajes: 44
    • Ver Perfil
Re: Extraño comportamiento de destructor
« Respuesta #2 en: Lunes 12 de Octubre de 2009, 20:48 »
0
Hola,
muchas gracias!!
Pues por fin ha funcionado bien, y era por lo que decias!!

Respecto al tema del singleton:
Citar
Pero no entiendo: ¿usas CGeneralLogger en forma de Singleton? es lo que me parece porque usas la funcion GetInstance()
Me parece raro porque:
1. Si CGeneralLogger es un singleton, no hay que instanciarlo fuera de su-mismo (es por eso que los constructores son declarados en privado en el pattern Singleton)
2. CGeneralLogger parece dedicada a tener herencia (hablas de la funcion virtual processMessage, supongo que es un patrono Template Method y que tendras hijos de CGeneralLogger que implementan processMessage de maneras distintas ¿no?)

No es exactamente asi:
Construi otra clase, llamada CentralLog, que era un singleton. En ella concentro todos los mensajes de la aplicacion, y le añado "listeners" para recoger los mensajes. Es una implementacion un poco grossa del patron observable :)

CGeneralLogger es un listerner, y no es un singleton. si te fijas, en el main estan las lineas:
   
Código: C++
  1.   //Aqui creo un logger
  2.      CGeneralLogger glogger =
  3.                CGeneralLogger("Log333.txt",tools::GLog::LOGLEVEL_DEGUG); //esto es una implementacion de la interface listener
  4.  
  5.         // Aqui recojo una instancia del singleton GlobalLogger
  6.         tools::GLog::CGlobalLog *gLog;
  7.         gLog = tools::GLog::CGlobalLog::getInstance();   // gLog es el singleton
  8.  
  9.         // Aqui agrego la clase al log para que la llame en processMessage.
  10.         gLog->addListener(&glogger); //añado el listener la lista interna de clases de CentralLog
  11.  
  12.  

Es un poco mas complejo que el tipico logger pero me da mucha libertad para crear logear mensajes desde donde quiero, y por otro lado, recorgerlos donde quiero, filtrandolos por grupos y por nivel. Vaya, como Log4j pero en algo mas cutre :)

Muchas gracias por todo!