Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Violación de segmento ('core' generado)

Estas en el tema de Violación de segmento ('core' generado) en el foro de C/C++ en Foros del Web. Hola, estoy programando una calculadora de polinomios y todo funciona bien salvo el MCD. Se compila todo bien pero cuando corro el programa en la ...
  #1 (permalink)  
Antiguo 09/12/2015, 16:27
 
Fecha de Ingreso: diciembre-2015
Mensajes: 1
Antigüedad: 8 años, 11 meses
Puntos: 0
Pregunta Violación de segmento ('core' generado)

Hola, estoy programando una calculadora de polinomios y todo funciona bien salvo el MCD. Se compila todo bien pero cuando corro el programa en la opción 9 (MCD) aparece el mensaje de Violación de segmento ('core' generado).

Espero me pue
El código de mi programa es:

Código:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <math.h> //Se usa solo para la opción de evaluar polinomios

using namespace std;

class Poli : public vector<double> {
      public:
       Poli();
       int Gr() const;
       ostream& Print(ostream& os) const;
};

Poli::Poli() : vector<double>()
{ }

ostream& Poli::Print(ostream& os) const
{
    for (int k=0; k<this->size(); k++)
       os << " + " << (*this)[k] << "x**" << k;
    return os;
}

ostream& operator << (ostream& os, const Poli& p)
{
    return p.Print(os);
}


int Poli::Gr() const
{
   int gr= 0;
   for (int k=0; k < (*this).size(); k++)
      if ( (*this)[k] != 0.0 )
          gr= k;
   return gr;
}

Poli Integral(const Poli& p)
{
   Poli r;
   int Gp= p.Gr();
   int k= 0;
   r.push_back(0);
   while (k<=Gp)
      {
       r.push_back( p[k] /(k+1) );
       k++;
      }

    return r;
}


Poli Derivada(const Poli& p)
{
   Poli r;
   int Gp= p.Gr();
   int k= 2;
   r.push_back(p[1]);
   while (k<=Gp)
      {
       r.push_back( p[k] *(k) );
       k++;
      }
    return r;
}

Poli Suma(Poli p, Poli q)
{
   Poli r;
   int Gp= p.Gr();
   int Gq= q.Gr();
   int k= 0;
   while (k<=Gp && k<=Gq)
      {
       r.push_back( p[k] + q[k] );
       k++;
      }
   while (k<=Gp)
      r.push_back( p[k++] );

   while (k<=Gq)
      r.push_back( q[k++] );

    return r;
}

Poli Resta(Poli p, Poli q)
{
   Poli r, t;
   int Gp= p.Gr();
   int Gq= q.Gr();
   int k= 0;
   while (k<=Gp && k<=Gq)
      {
       r.push_back( p[k] - q[k] );
       k++;
      }
   while (k<=Gp)
      r.push_back( p[k++] );

   while (k<=Gq)
      r.push_back( -q[k++] );

    return r;
}

Poli Mult(Poli p, Poli q)
{
  Poli r;
  int res[p.Gr()+q.Gr()+1];
  for(int c=0; c<=p.Gr()+q.Gr(); c++)
   res[c]=0;
  for(int i=0; i<=p.Gr(); i++)
  {
   for(int j=0; j<=q.Gr(); j++)
   {
     res[i+j]+=p[i]*q[j];
   }
  }
  for(int k=0; k<=p.Gr()+q.Gr(); k++)
  {
    r.push_back(res[k]);
  }

  return r;
}

Poli Div(Poli p, Poli q)
{ 
  Poli a, b, c, r, t;
  Poli s;
  s.push_back(0);
    double f[q.Gr()-p.Gr()];
    for(int i=0; i<=q.Gr()-p.Gr(); i++)
      f[i]=0;
    f[q.Gr()-p.Gr()]=q[q.Gr()]/p[p.Gr()];
    for(int j=0; j<=q.Gr()-p.Gr(); j++)
      a.push_back(f[j]);
    b=Mult(p, a);
    s = Suma(s, a);
    c=Resta(q, b);
  return s;
}

Poli Residuo(Poli p, Poli q)
{ 
  Poli a, b, c, r, t;
  Poli s;
  s.push_back(0);
    double f[q.Gr()-p.Gr()];
    for(int i=0; i<=q.Gr()-p.Gr(); i++)
      f[i]=0;
    f[q.Gr()-p.Gr()]=q[q.Gr()]/p[p.Gr()];
    for(int j=0; j<=q.Gr()-p.Gr(); j++)
      a.push_back(f[j]);
    b=Mult(p, a);
    s = Suma(s, a);
    c=Resta(q, b);
  return c;
}

Poli MCD(Poli p, Poli q)
{
  Poli m;
  do
    {
      m= Residuo(p, q);
      q = p;
      p = m;
    }
  while(m.Gr() != 0);
  return m;
}

int main()
{

   Poli p;
   p.push_back(8);
   p.push_back(2);
   p.push_back(0);
   p.push_back(1);

   Poli q;
   q.push_back(2);
   q.push_back(0);
   q.push_back(4);
   q.push_back(1);
   q.push_back(4);
   q.push_back(9);
   
 
   Poli r, s;
   int b, a;
   cout<<"CALCULADORA DE POLINOMIOS\n";
   cout<<"Por favor elija la operación que quiera hacer con los polinomios ingresados\n";
   cout<<"1 Sumar los polinomios p y q\n";
   cout<<"2 Restar los polinomios p y q\n";
   cout<<"3 La integral de p y la integral de q\n";
   cout<<"4 La derivada de p y la derivada de q\n";
   cout<<"5 Evaluar p y q en un punto elegido por el usuario\n";
   cout<<"6 Multiplicar p y q\n";
   cout<<"7 Dividir q (el polinomio de mayor grado) entre p\n";
   cout<<"8 El residuo de dividir q entre p\n";
   cout<<"9 El MCD de los polinomios q (de mayor grado) y p\n"<<endl;
   cin>>a;

   switch(a)
   {
     case 1:
     {
       r= Suma(p, q);
       cout<<"La suma de los polinomios p y q es:\n";
       cout<< r << endl;
       cout<<"\n El grado de la suma es:"<< r.Gr() << endl;
     }
     break;
    case 2:
     {
       r= Resta(p, q);
       cout<<"La resta de los polinomios p y q es:\n";
       cout<< r << endl;
       cout<<"\n El grado de la resta es:"<< r.Gr() << endl;
     }
     break;
    case 3:
     {
       r= Integral(p);
       s= Integral(q);
       cout<<"La integral del polinomio p es:\n";
       cout<< r <<" + c"<< endl;
       cout<<"\n El grado de la integral de p es: "<< r.Gr() << endl;
       cout<<"\n La integral del polinomio q es:\n";
       cout<<s<< " + c"<< endl;
       cout<<"\n El grado de la integral de q es:"<< s.Gr() << endl;
     }
     break;
    case 4:
     {
      r= Derivada(p);
      s= Derivada(q);
      cout<<"La derivada del polinomio p es:\n";
      cout << r << endl;
      cout<<"El grado de la derivada de p es: "<< r.Gr() << endl;
      cout<<"La derivada del polinomio q es:\n";
      cout << s << endl;
      cout<<"El grado de la derivada de q es: "<< s.Gr() << endl;
     }
     break;
    case 5:
     {
      cout<<"Ingrese el número donde quiere evaluar a los polinomios p y q: "<<endl;
      cin>>b;
      int sum1=0, par1;
      for(int j=0; j<=p.Gr(); j++)
      {
       par1=p[j]*pow(b,j);
       sum1+=par1;
      }
      int sum2=0, par2;
      for(int j=0; j<=q.Gr(); j++)
      {
       par2=q[j]*pow(b,j);
       sum2+=par2;
      }
      cout<<"\n El valor del polinomio p en "<<b<<" es: "<<sum1<<endl;
      cout<<"\n El valor del polinomio q en "<<b<<" es: "<<sum2<<endl;
     }
     break;
    case 6:
     {
      Poli r;
      r= Mult(p, q);
      cout<<"La multiplicación de p y q es:\n";
      cout<<r<< endl;
      cout<<"El grado de la multiplicación es: "<<r.Gr()<<endl;
     }
     break;
    case 7:
     {
       Poli r;
       r= Div(p, q);
       cout<<"La división q entre p es:\n";
       cout<< r << endl;
       cout<<"El grado de la división es: "<<r.Gr()<<endl;
     }
     break;
   case 8:
     {
       Poli r;
       r= Residuo(p, q);
       cout<<"La división q entre p es:\n";
       cout<< r << endl;
       cout<<"El grado del residuo es: "<<r.Gr()<<endl;
     }
     break;
   case 9:
     {
       Poli r;
       r=MCD(p, q);
       cout<<"El MCD de los polinomios p y q es:\n";
       cout<<r <<endl;
     }
     break;
   }
  

   return EXIT_SUCCESS;
}
  #2 (permalink)  
Antiguo 10/12/2015, 02:34
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Violación de segmento ('core' generado)

Que el programa te arroje los resultados esperados en todos los apartados menos en ese no implica necesariamente que el programa esté bien:

Código C++:
Ver original
  1. class Poli : public vector<double>

Has de saber que el destructor de std::vector<T> no es virtual. Esto quiere decir que si usas polimorfismo te puedes encontrar con la desagradable sorpresa de que no se invoca al destructor de Poli, con lo que toda la memoria reservada por este objeto o por sus variables internas se quedará en el limbo.

Código C++:
Ver original
  1. class NoVirtualA
  2. {
  3.   public:
  4.     NoVirtualA(){}
  5.  
  6.     ~NoVirtualA()
  7.     { std::cout << "NoVirtualA::~NoVirtualA()" << std::endl; }
  8. };
  9.  
  10. class NoVirtualB : public NoVirtualA
  11. {
  12.   public:
  13.     NoVirtualB(){}
  14.  
  15.     ~NoVirtualB()
  16.     { std::cout << "NoVirtualB::~NoVirtualB()" << std::endl; }
  17. };
  18.  
  19. class VirtualA
  20. {
  21.   public:
  22.     VirtualA(){}
  23.  
  24.     virtual ~VirtualA()
  25.     { std::cout << "VirtualA::~VirtualA()" << std::endl; }
  26. };
  27.  
  28. class VirtualB : public VirtualA
  29. {
  30.   public:
  31.     VirtualB(){}
  32.  
  33.     ~VirtualB()
  34.     { std::cout << "VirtualB::~VirtualB()" << std::endl; }
  35. };
  36.  
  37. int main()
  38. {
  39.   std::cout << "Caso 1: Se llama a los dos destructores:" << std::endl;
  40.   NoVirtualB* noVirtualB = new NoVirtualB;
  41.   delete noVirtualB;
  42.  
  43.   std::cout << "Caso 2: Dónde quedó el segundo destructor?" << std::endl;
  44.   NoVirtualA* noVirtualA = new NoVirtualB;
  45.   delete noVirtualA;
  46.  
  47.   std::cout << "Caso 3: Ahora si aparecen los dos destructores:" << std::endl;
  48.   VirtualA* virtualA = new VirtualB;
  49.   delete virtualA;
  50. }

Lo suyo, más que herencia, sería tirar de composición, es decir, hacer que el vector fuese un miembro de Poli. Claro está te obligaría a implementar métodos para añadir, eliminar, acceder y modificar los diferentes monomios pero el diseño no sería problemático.

Otro error que tienes es la comparación de datos de tipo double:

Código C++:
Ver original
  1. int Poli::Gr() const
  2. {
  3.    int gr= 0;
  4.    for (int k=0; k < (*this).size(); k++)
  5.       if ( (*this)[k] != 0.0 )
  6.           gr= k;
  7.    return gr;
  8. }

Si te han explicado las cosas por orden, habrás tenido que ver cómo se almacenan los números decimales en la memoria del ordenador (eso de la mantisa, el exponente, ...). Así mismo habrás visto que un número decimal no tiene por qué tener una representación exacta en binario. Hay números muy tontos como, por ejemplo, 0,3 que en binario tendrá infinitos dígitos: 0.01010101... queda claro entonces que por mucho que te esfuerces no vas a poder almacenar exactamente 0,3 en 32 bits (o 64 o los que te de la gana).

La forma correcta de comparar decimales es asumir que dos números son iguales si se parecen lo suficiente... esto es |A - B| < ALGO. Normalmente ALGO puedes sustituirlo por 1e-4 o 1e-6... si usas double puedes aumentar la precisión pero normalmente no te va a aportar gran cosa. Por cierto, nota que me estoy quedando con el valor absoluto de la resta.

Más cosillas:

Código C++:
Ver original
  1. int Poli::Gr() const
  2. {
  3.    int gr= 0;
  4.    for (int k=0; k < (*this).size(); k++)
  5.       if ( (*this)[k] != 0.0 )
  6.           gr= k;
  7.    return gr;
  8. }

Si en el vector almacenas en la posición 0 el monomio menos representativo y de ahí en orden hacia arriba... por qué fuerzas al código a recorrer todo el polinomio desde el principio si lo único que te interesa es el último valor?? Funcionar funciona, pero la forma de hacerlo no es desde luego la más adecuada. Lo suyo sería empezar desde el final y quedarse con el primer valor distinto de 0... después de eso salir del bucle porque no tiene sentido seguir comprobando valores.


Seguimos:

Código C++:
Ver original
  1. Poli Residuo(Poli p, Poli q)
  2. {
  3.   Poli a, b, c, r, t;
  4.   Poli s;
  5.   s.push_back(0);
  6.     double f[q.Gr()-p.Gr()];
  7.     for(int i=0; i<=q.Gr()-p.Gr(); i++)
  8.       f[i]=0;
  9.     f[q.Gr()-p.Gr()]=q[q.Gr()]/p[p.Gr()];
  10.     for(int j=0; j<=q.Gr()-p.Gr(); j++)
  11.       a.push_back(f[j]);
  12.     b=Mult(p, a);
  13.     s = Suma(s, a);
  14.     c=Resta(q, b);
  15.   return c;
  16. }

En la función anterior centrémonos en la línea:

Código C++:
Ver original
  1. double f[q.Gr()-p.Gr()];

¿Qué sucede si p.Gr() es mayor que q.Gr()? Se puede crear un array con tamaño negativo? la respuesta rápida es que no. ¿Es muy importante esto? pse... si miramos otra función:

Código C++:
Ver original
  1. Poli MCD(Poli p, Poli q)
  2. {
  3.   Poli m;
  4.   do
  5.     {
  6.       m= Residuo(p, q); // <<<--- AQUI!!!
  7.       q = p;
  8.       p = m;
  9.     }
  10.   while(m.Gr() != 0);
  11.   return m;
  12. }

Pues lo mismo empieza a tener sentido el error que comentas :)

Y ya como bonus un pequeño detalle. Pasar a una función objetos por valor implica hacer una copia de los mismos. Para lo que estás haciendo ahora mismo no es significativo, pero es una mala práctica porque reduce muchísimo el rendimiento. Lo más común es pasar los objetos como referencias constantes, lo que evita crear una copia en cada llamada:

Código C++:
Ver original
  1. Poli MCD(const Poli& p, const Poli& q)

Lo bueno de aplicar esta solución es que no tienes que modificar para nada el código de la función!!!

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #3 (permalink)  
Antiguo 10/12/2015, 14:08
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Violación de segmento ('core' generado)

No sabía que se podía heredar de una plantilla, o de un contenedor, mejor dicho
__________________
Mi calculadora en Qt
  #4 (permalink)  
Antiguo 10/12/2015, 23:09
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Violación de segmento ('core' generado)

Cita:
Iniciado por dehm Ver Mensaje
No sabía que se podía heredar de una plantilla, o de un contenedor, mejor dicho
Es más correcto decir que no es seguro heredar de una clase que no tiene su destructor como virtual.

Si la plantilla tiene el destructor virtual no hay ningún problema. Lo que sucede es que los contenedores de la STL no tienen el destructor marcado como virtual.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Etiquetas: core, funcion, int, programa, segmento
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:42.