Segment violation, problem in pointers or dynamic memory?

0

Good I was trying to practice with vectors with dynamic memory and I got this error when executing:

Violación de segmento ('core' generado)

The fact is that sometimes it works, so it leaves me a little confused, this is my code:

#include <iostream>
#include <fstream> // ifstream
using namespace std;

struct VecDin {
   int *datos;
   int n;
};

// FIXME 1: Redimensions v para que se quede con "nuevo" elementos
void ReSize(VecDin& v,int nuevo)
{   
    if(nuevo >= 0) {
        if(nuevo != v.n) {  
            if(nuevo != 0) {
                int *datos_nuevos;
                datos_nuevos = new int[nuevo];
                if(v.n >  0) {
                    int minimo = v.n < nuevo ? v.n : nuevo;
                    for(int i = 0; i < minimo; i++)
                        datos_nuevos[i] = v.datos[i];
                    delete[] v.datos;
                }
                v.datos = datos_nuevos;
                v.n = nuevo;
            }
            else {
                delete[] v.datos;
                v.datos = 0;
                v.n = 0;
            }   
        }
    }

}

// FIXME 2: Lee objetos int hasta final de flujo y devuelve VecDin con los  datos (usa ReSize)
VecDin LeerVecDin(istream& flujo)
{
    VecDin v;
    int n = 1;

    while(flujo.good()) {
        ReSize(v,n);
        flujo >> v.datos[n-1];
        ++n;
    }
    return v;
}

// FIXME 3: Muestra en un flujo de salida los datos enteros de un VecDin     (ver main)

void Mostrar(VecDin vector, ostream& os)
{
    for(int i = 0; i < vector.n || !os.good(); i++)
        os << vector.datos[i] << " ";
}

// FIXME 3: Libera la memoria reservada en un VecDin (ver main)

void Liberar(VecDin v)
{
    delete[] v.datos;
    v.n = 0;
}

int main(int argc, char *argv[])
{
   VecDin v= {0,0};

   if (argc==1)
      v= LeerVecDin(cin);
   else {
      ifstream f(argv[1]);
      if (!f) {
         cerr << "Error: Fichero " << argv[1] << " no válido." << endl;
         return 1;
      }
      v= LeerVecDin(f);
   }

   Mostrar(v,cout);
   Liberar(v); // Libera la memoria reservada
}

If you could give me a clue as to why, as I suppose it is what happens, access outside the memory that corresponds to it would help me a lot.

Thank you!

    
asked by Hesterions 21.05.2017 в 19:34
source

1 answer

0
VecDin LeerVecDin(istream& flujo)
{
    VecDin v; // (1)
    int n = 1;

    while(flujo.good()) {
        ReSize(v,n); // (2)
        flujo >> v.datos[n-1];
        ++n;
    }
    return v;
}

We are going to analyze this function:

  • How much are v.datos and% v.n ? Since you have not declared a constructor for VecDin and you have not given it a specific value, we can say that the pointer v.datos points to a random address (= garbage) and that the value of v.n is equally random.
  • How does the function Resize behave in this situation? If you check the function you will see that there are two paths that try to free the memory reserved by v.n . As there will not be such a memory reserve, these two paths will involve closing the application (you can not free memory that you have not reserved). If you are lucky enough to dodge those two paths what will happen is that v.datos will not point to a valid memory address ... that the program fails to access this memory will depend on the luck and modernity of your Operating System (the most modern do not forgive one).
  • The solution is as simple as initializing the variable members of the object:

    VecDin v;
    v.datos = 0;
    v.n = 0;
    

    Although as you are programming in C ++, which is assumed to be object-oriented, what is expected then is that you use the default constructor:

    struct VecDin
    {
      int *datos;
      int n;
    
      VecDin() : datos(0), n(0)
      { }
    };
    

    Final bonus

    The status of streams is not updated until a read / write is made that causes an error. That is, before an entry ... 1 2 3 n , this loop:

    int n = 1;
    while(flujo.good()) {
        ReSize(v,n);
        flujo >> v.datos[n-1];
        ++n;
    }
    

    The output will result: 1 2 3 0 . This happens because the flujo.good check is not being made at the correct site. The following example would be more correct:

    int n = 0;
    int variable;
    flujo >> variable;
    while(flujo.good()) {
        ++n;
        ReSize(v,n);
        v.datos[n-1] = variable;
        flujo >> variable;
    }
    

    Now the reading is done on a variable dummy . If the reading fails then that value is not carried to v .

        
    answered by 22.05.2017 / 08:51
    source