Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: marlboreano en 15 Enero 2015, 16:03 pm



Título: Segmentation Fault C++
Publicado por: marlboreano en 15 Enero 2015, 16:03 pm
Hola a todos.
Este es mi primer posteo en esta muy buena página (que desde hace varios años visito a menudo para responder todas las dudas que tenga), así que les pido perdón desde ya por mi ignorancia en los temas siguientes.

Estoy intentando hacer un proyecto en C++ integrando wxFormBuilder y me encuentro con un pequeño problema: Segmentation Fault.
En sí, el problema radica en que quiero acceder a una posición en memoria inválida, aunque no encuentro dónde (ya que el proyecto es bastante grande). Intenté depurar paso a paso y me remarca las líneas donde comienza una de mis clases (no sé por qué) y la línea en la cual intento guardar en un vector, un valor.

En sí, la lógica de mi programa (resumida) es la siguiente:

Clase Mayor tiene un vector (siempre standart) de Clase Hija1, ésta a su vez, tiene un vector de Clase Nieta1.

Cuando intento guardar datos desde mayor a través de un método "guardar Hija1" no surge ningún problema, es más, puedo mostrar los datos de Hija1 (dependiendo la posición que le dé en los argumentos) sin problema alguno; pero el problema me surge cuando quiero mostrar los datos de "Nieta1".

Ej:

1) vector<Mayor> v_Mayor; Hija1 h1; Nieta1 n1;

2)v_Mayor.Agregar(h1); (Dentro del Método "Agregar" hace el push_back correspondiente).

3)v_Mayor.RetornaHija(v_Mayor.size()-1).AgregarNieta(n1);

4)cout<<v_Mayor[v_Mayor.size()-1].RetornaNieta(0).MostrameDatos()<<endl;

Acá, en la línea 4, es donde surge el error de Segmentación.


* Todas las clases tienen sobrecargados los operadores [], <, ==, =.
** El 0 en "RetornarNieta(0)" es más bien para no complicar más y que sólo nos retorne la primera agregada.
*** Cada clase tiene a su vez, un método para cargar, mostrar, eliminar y retornar las cantidades que hay de cada subtipo dentro de una.

Desde ya, les agradezco todas las ayudas, retos y observaciones que me puedan brindar.


Título: Re: Segmentation Fault C++
Publicado por: _Enko en 15 Enero 2015, 16:25 pm
Me parece que tienes un problema de herencia con datos privados.

Clase nieta debería ser friend de clase mayor, o pasar los datos de la herencia como protected y no private.

Eso es una posibilidad, no te sabría decir bien, sería mas facil sabiendo como está construidas las tres clases.

O bien
Código:
cout<<v_Mayor[v_Mayor.size()-1].RetornaNieta(0).MostrameDatos()<<endl;

Deberia de ser algo como
Código:
cout<<v_Mayor[v_Mayor.size()-1].v_Hija[x].RetornaNieta(0).MostrameDatos()<<endl;


Recuerda que tambien para simplificar el nesting de vectores puedes tener un vector de la propia clase
Código:
class CHIJA{
public:
   ...
private:
   vector<CHIJA> contenido;
};
Saludos.


Título: Re: Segmentation Fault C++
Publicado por: marlboreano en 15 Enero 2015, 16:54 pm
Hola _Enko, te agradezco por la pronta respuesta y por el interés en ayudarme.
Mirá, estuve haciendo rápido un código parecido al que tengo para que se entienda mejor cuál es el error.

Código:
#include <iostream>
#include <string>
#include <vector>
using namespace std;


class Nieta {
string nom;
int edad;
vector<int> datos;
public:
Nieta(void) {
nom = ""; edad = 0; datos.clear();
}
Nieta(const string &Nombre, const int &Edad) {
nom = Nombre; edad = Edad; datos.clear();
}
bool CargarNombreyEdad(const string &Nombre, const int &Edad) {
nom = Nombre; edad = Edad;
return (nom == Nombre && edad == Edad)?true:false;
}
bool AgregarDato(const int &UnDato) {
unsigned int tam = datos.size();
datos.push_back(UnDato);
return (tam == datos.size())?true:false;
}
int MostrarDato(const int &Indice) {
return datos[Indice];
}
bool EliminarDato(const int &Indice) {
unsigned int cant = datos.size();
datos.erase(datos.begin()+Indice);
if (datos.size() < cant) return true;
return false;
}
string MostrarNombre(void) {
return nom;
}
};

class Hija {
string nom;
int edad;
vector<Nieta> v_Nietas;
public:
Hija(void) {
nom = ""; edad = 0; v_Nietas.clear();
}
Hija(const string &Nombre, const int &Edad) : nom(Nombre), edad(Edad) {
v_Nietas.clear();
}
bool CargarNombreyEdad(const string &Nombre, const int &Edad) {
nom = Nombre; edad = Edad;
return (nom == Nombre && edad == Edad)?true:false;
}
bool AgregarNieta(const Nieta &UnaNieta) {
unsigned int tam = v_Nietas.size();
v_Nietas.push_back(UnaNieta);
return (tam == v_Nietas.size())?true:false;
}
Nieta MostrarNieta(const int &Indice) {
return v_Nietas[Indice];
}
bool EliminarNieta(const int &Indice) {
unsigned int cant = v_Nietas.size();
v_Nietas.erase(v_Nietas.begin()+Indice);
if (v_Nietas.size() < cant) return true;
return false;
}

};

class Madre {
string nom;
int edad;
vector<Hija> v_Hijas;
public:
Madre(void) {
nom = ""; edad = 0; v_Hijas.clear();
}
Madre(const string&Nombre, const int&Edad) : nom(Nombre), edad(Edad) {
v_Hijas.clear();
}
bool CargarNombreyEdad(const string&Nombre, const int&Edad) {
nom = Nombre; edad = Edad;
return (nom == Nombre && edad == Edad)?true:false;
}
bool AgregarHija(const Hija&UnaHija) {
unsigned int tam = v_Hijas.size();
v_Hijas.push_back(UnaHija);
return (tam == v_Hijas.size())?true:false;
}
Hija MostrarHija(const int&Indice) {
return v_Hijas[Indice];
}
bool EliminarHija(const int&Indice) {
unsigned int cant = v_Hijas.size();
v_Hijas.erase(v_Hijas.begin()+Indice);
if (v_Hijas.size() < cant) return true;
return false;
}
};



int main(int argc, char *argv[]) {
vector<Madre> global_madres;
Madre m1;
global_madres.push_back(m1);
Hija h1;
global_madres[0].AgregarHija(h1);
Nieta n1;
global_madres[0].MostrarHija(0).AgregarNieta(n1);
cout<<global_madres[0].MostrarHija(0).MostrarNieta(0).MostrarNombre()<<endl; //KABOOM, acá explota :(
return 0;
}


Disculpá el desorden, pero como te comentaba, lo hice rápido para que puedas ver más o menos como es el código que me genera error en mi proyecto (está todo en un cpp :P).

Si encontrás cuál es el error, desde ya te agradezco muchísimo.
Nota: Pensaba que el problema radicaba en que las clases se inicializaban con basura, pero en los constructores (tanto en el parametrizado como en el vacío) les cargo "algo" aunque sea.

Nuevamente, muchas gracias. Saludos.

Nota: Depurando paso a paso, me remarca las líneas 7 (Declaración clase Nieta), línea 62 (retorno del método "MostrarNieta(const int& Indice)") y la línea 114 (cuando deseo mostrar el nombre de la nieta desde cout).



_Enko, el tema es que no necesariamente serán amigas las clases, ni tampoco necesito un vector de la misma clase dentro de ella (me suena raro y ya planteé la jerarquía de esa forma).
Esto :"cout<<v_Mayor[v_Mayor.size()-1].v_Hija
  • .RetornaNieta(0).MostrameDatos()<<endl;" tampoco podría hacerlo, debido a que v_Hija está en el ámbito privado de la clase "Madre".

Si bien, en este ejemplo son bastante similares y podría usar las clases Hija y Nieta heredadas de Madre, en el caso concreto no me serviría, puesto que difieren de mis clases reales (y bastante).
Si alguien puede blanquear el asunto de Segmentación, le agradezco. Saludos.


Título: Re: Segmentation Fault C++
Publicado por: marlboreano en 15 Enero 2015, 17:56 pm
_Enko, el tema es que no necesariamente serán amigas las clases, ni tampoco necesito un vector de la misma clase dentro de ella (me suena raro y ya planteé la jerarquía de esa forma).
Esto :"cout<<v_Mayor[v_Mayor.size()-1].v_Hija
  • .RetornaNieta(0).MostrameDatos()<<endl;" tampoco podría hacerlo, debido a que v_Hija está en el ámbito privado de la clase "Madre".

Si bien, en este ejemplo son bastante similares y podría usar las clases Hija y Nieta heredadas de Madre, en el caso concreto no me serviría, puesto que difieren de mis clases reales (y bastante).
Si alguien puede blanquear el asunto de Segmentación, le agradezco. Saludos.


Título: Re: Segmentation Fault C++
Publicado por: _Enko en 15 Enero 2015, 18:02 pm
Código
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. using namespace std;
  5.  
  6.  
  7. class Nieta {
  8. string nom;
  9. int edad;
  10. public:
  11. Nieta(void) {
  12. nom = "nieta"; edad = 0;
  13. }
  14. Nieta(const string Nombre, const int Edad) {
  15. nom = Nombre; edad = Edad;
  16. }
  17. string MostrarNombre(void) {
  18. return nom;
  19. }
  20. };
  21.  
  22. class Hija {
  23. string nom;
  24. int edad;
  25. vector<Nieta> v_Nietas;
  26. public:
  27.    string MostrarNombre(){
  28.        return nom;
  29.    }
  30. Hija(void) {
  31. nom = "hija"; edad = 0; v_Nietas.clear();
  32. }
  33. Hija(const string Nombre, const int Edad) : nom(Nombre), edad(Edad) {
  34. v_Nietas.clear();
  35. }
  36. void AgregarNieta(const Nieta UnaNieta) {
  37. v_Nietas.push_back(UnaNieta);
  38. }
  39. Nieta& MostrarNieta(const int Indice) {
  40. return v_Nietas[Indice];
  41. }
  42.  
  43. };
  44.  
  45. class Madre {
  46. string nom;
  47. int edad;
  48. vector<Hija> v_Hijas;
  49. public:
  50. Madre(void) {
  51. nom = "madre"; edad = 0; v_Hijas.clear();
  52. }
  53. Madre(const string Nombre, const int Edad) : nom(Nombre), edad(Edad) {
  54. v_Hijas.clear();
  55. }
  56. bool AgregarHija(const Hija UnaHija) {
  57. unsigned int tam = v_Hijas.size();
  58. v_Hijas.push_back(UnaHija);
  59. return (tam == v_Hijas.size())?true:false;
  60. }
  61. Hija& MostrarHija(const int Indice) {
  62. return v_Hijas[Indice];
  63. }
  64. };
  65.  
  66.  
  67.  
  68. int main(int argc, char *argv[]) {
  69. vector<Madre> global_madres;
  70. global_madres.push_back(Madre());
  71. global_madres[0].AgregarHija(Hija());
  72. global_madres[0].MostrarHija(0).AgregarNieta(Nieta());
  73. cout << global_madres[0].MostrarHija(0).MostrarNombre() << endl;
  74.    cout<<global_madres[0].MostrarHija(0).MostrarNieta(0).MostrarNombre()<<endl; //KABOOM, acá explota :(
  75. int i;
  76. cin >> i;
  77.    return 0;
  78. }
  79.  

Basicamente esta fue la modificacion
Código
  1. Hija &MostrarHija(const int&Indice) {
  2. return v_Hijas[Indice];
  3. }
  4.  

Necesitas retornar una referencia al objeto y no el objeto de por si porque hacec
Citar
MostrarHija(0).MostrarNieta(0).MostrarNombre()

Saludos.


Título: Re: Segmentation Fault C++
Publicado por: marlboreano en 15 Enero 2015, 18:05 pm
Yo sabía que era un error de punteros o referencias (los mismos errores pelotudos de siempre xD)...¡pasa que no encontraba dónde!
_Enko, mi héroe en este lío jajaja. ¡No sabes lo agradecido que estoy! Me solucionaste un garrón de mil líneas.
Muchísimas gracias, pueden dar por cerrado el tema.


Título: Re: Segmentation Fault C++
Publicado por: _Enko en 15 Enero 2015, 18:15 pm
De nada :)

No tenia el visual studio a mano que posee un decente depurador (dev c++... como que es la pobreza) asi que no salto a la vista depurando  :D
Con Visual Studio creo que hubiera sido mas facil encontarlo.