Un saludo.
Estoy haciendo un ejercicio corto y que en principio no debería dar más problemas, pero mis fieles amigos los segmentation fault ya están aquí. El programa trata de la gestión de un blog. Lo que a nosotros nos interesa es la relación de composición entre una entrada y sus comentarios, que son punteros dentro de un array, que a su vez es un atributo de la entrada:
#ifndef ENTRADA_H
#define ENTRADA_H
#include <string>
#include <stdexcept>
#include "Comentario.h"
class Entrada {
public:
Entrada();
Entrada(std::string titulo, std::string fecha, std::string texto);
Entrada(const Entrada& orig);
virtual ~Entrada();
void addComentario(Comentario *comentario);
void eliminarComentario(int cual);
std::string getTexto();
std::string getTitulo();
std::string getFecha();
int getNumComentarios();
Entrada& setTexto(std::string &texto);
Entrada& setTitulo(std::string &titulo);
Entrada& setFecha(std::string &fecha);
Comentario& getComentario (int cual);
static const int MAX_COMENTARIOS = 30;
private:
std::string _titulo = "";
std::string _texto = "";
std::string _fecha = "";
int _numComentarios = 0;
Comentario *_comentarios[MAX_COMENTARIOS];
};
#endif /* ENTRADA_H */
Como es lógico, si se elimina una entrada los comentarios mueren con ella, no siguen existiendo (es una relación de composición). Pues bien, el destructor de la entrada queda tal que así:
Entrada::~Entrada() {
for (int i = 0; i < _numComentarios; i++){ //Con la entrada se destruyen los comentarios
delete _comentarios[i];
}
}
_comentarios[] se rellena en el propio main utilizando el método addCometnario de la clase Entrada:
void Entrada::addComentario(Comentario* comentario) {
if (_numComentarios == MAX_COMENTARIOS)
throw std::string ("Entrada::addComentario: No caben mas comentarios");
_comentarios[_numComentarios] = comentario;
_numComentarios++;
}
En el main queda tal que así:
Entrada entrada1 ("Bienvenida", "1-1-2010", "Bienvenidos al nuevo blog");
Comentario com1 ("AAA", "Hola!!!", "3-1-2010");
entrada1.addComentario(&com1);
Después de lo cual hay algunos cout y algunos try-catch que sí se comportan como se espera.
¿El problema? Al llegar al return 0 e ir a finalizar el programa, cuando se llama a los destructores de los objetos automáticos, es cuando se produce el segmentation fault, concretamente al ir a destruirse la entrada. El bucle for se ejecuta una vez (hay un comentario), y en esa ejecución se produce el segmentation fault al llamar al destructor de Comentario, que está por defecto, sin nada especial (en esa clase los atributos son objetos std::string sin arrays ni nada "especial").
Ahora me estoy planteando la hipótesis de que esto se producía porque se destruía antes el comentario que la entrada (o al revés), llamándose siempre a un destructor sin objeto que destruir, con lo cual he probado a crearlos manualmente con new y a borrarlos también manualmente con delete y, en efecto, ya no se produce el error (obviamente solo hago delete entrada1
, pues ahí ya se elimina el comentario también):
Entrada *entrada1 = new Entrada ("Bienvenida", "1-1-2010", "Bienvenidos al nuevo blog");
Comentario *com1 = new Comentario ("AAA", "Hola!!!", "3-1-2010");
entrada1->addComentario(com1);
//Resto del main sin mayor importancia
delete entrada1;
//delete com1 no se pone, pues ya lo ha eliminado el destructor de la entrada
return 0;
Pero claro, esto ya me lleva a plantearme: ¿es imposible hacerlo con objetos automáticos, al no poder controlar la llamada a los destructores?
Gracias. Saludos.