c++ segmentation fault when copying a matrix

I'm having a problem with a matrix, and the problem is when I try to copy it it gives me the error 'Segmentation Fault'. This is the code involved:

main.cpp

void principal(Tauler &tauler) {
    GeneradorPuzzle puzzle;
    pilaMoviments pilaMovs;
    int nPuzzle, cont=0;
    bool valid;

    cout << "JOC DEL RUSH HOUR" << endl;
    cout << "ENTRA EL PUZZLE A JUGAR:" << endl;
    cin >> nPuzzle;
    valid=puzzle.esPuzzleValid(nPuzzle);
    if(!valid) {
        do {
            cout << "PUZZLE NO VALID. ENTRA EL PUZZLE A JUGAR:" << endl;
            cin >> nPuzzle;
            valid=puzzle.esPuzzleValid(nPuzzle);
        }while(!valid);
    }
    puzzle.posarPuzzleActiu(nPuzzle);
    tauler=Tauler(puzzle.midaPuzzle(),puzzle.totalVehicles());

    for(int i=0;i<puzzle.totalVehicles();i++) {
        Vehicle v(cont, puzzle.midaVehicle(i),puzzle.filaVehicle(i),puzzle.columnaVehicle(i),puzzle.direccioVehicle(i));
        valid=tauler.esValid(v);
        if(valid) {
            tauler.processar(v,cont);
            cont++;
        }
    }
}
int main() {
    pilaMoviments pilaMovs;
    Tauler tauler;
    char opcio;

    principal(tauler);
    tauler.mostrar();
    mostrarMenu();
    do {
        cout << "ENTRA OPCIO:" << endl;
        cin >> opcio;
        tractarOpcio(tauler,pilaMovs,opcio);
    }while(opcio!='X');
    return 0;
}

Tauler.cpp

Tauler::Tauler() {
    a_f=a_surt=a_n=a_valids=0;
    a_mp=NULL;
}
Tauler::Tauler(const Tauler &t) {
    a_f=t.a_f;
    a_n=t.a_n;
    a_surt=t.a_surt;
    a_valids=t.a_valids;
    reservarMemoria();
    copiar(t);
}
Tauler::Tauler(int nf, int nv) {
    a_f=nf;
    a_n=nv;
    a_v=new Vehicle[a_n];
    reservarMemoria();
    for(int j=0;j<a_f;j++)
        for(int i=0;i<a_f;i++)
            a_mp[i][j]='-';
}

Tauler::~Tauler() {
    alliberarMemoria();
}

// OPERADORS

Tauler& Tauler::operator=(const Tauler& y) {
    if (this!=&y) {
        alliberarMemoria();
        reservarMemoria();
        copiar(y);
    }
    return *this;
}

// METODES PRIVATS

void Tauler::copiar(const Tauler &t) {
    a_f=t.a_f;
    a_n=t.a_n;
    a_surt=t.a_surt;
    a_valids=t.a_valids;
    for(int i=0;i<a_f;i++) {
        for(int j=0;j<a_f;j++)
            a_mp[i][j]=t.a_mp[i][j];
    }
}
void Tauler::alliberarMemoria() {
    for(int i=0;i<a_f;i++)
        delete [] a_mp[i];  // s'alliberen les taules horitzontals
    delete [] a_mp;
}
void Tauler::reservarMemoria() {
    a_mp=new char*[a_f];
    for(int i=0;i<a_f;i++)
        a_mp[i]=new char[a_f];
}

Tauler.h

#ifndef TAULER_H
#define TAULER_H
#include "Vehicle.h"
#include "pilaMoviments.h"

class Tauler {
    // La classe que guardara la informacio del Tauler
    public:
        // CONSTRUCTORS I DESTRUCTOR
        Tauler();
        //Pre: --; Post: Posa Tauler per defecte.
        Tauler(int nf, int nv);
        //Pre: nf i nv entrats correctament. Post: Posa Tauler amb les files i el nombre de vehicles que li hem entrat.
        Tauler(const Tauler &t);
        //Pre: Tauler correcte. Post: Fa una copia de Tauler i li diu t.
        ~Tauler();
        //Pre: --; Post: Memoria alliberada.

        // OPERADOR
        Tauler &operator=(const Tauler &e);

        // CONSULTORS
        int Files() const;
        //Pre: Files del Tauler correctes. Post: Retorna les files i columnes del Tauler.
        int filaSurtida() const;
        //Pre: Files del Tauler correctes. Post: Retorna la fila de surtida del Tauler.
        int Vehicles() const;
        //Pre: a_valids del Tauler correctes. Post: Retorna el nombre de Vehicles valids del tauler.
        bool fiPartida() const;
        //Pre: Vehicle 'A' al tauler. Post: Retorna true si el Vehicle 'A' esta a la ultima columa de la fila de surtida, altrament retorna false.
        bool esValid(Vehicle v) const;
        //Pre: Parametres del Vehicle v entrats correctament. Post: Retorna true si el vehicle es pot posar correctament dins el tauler. False si no es pot posar.
        bool xoquen(Vehicle v, Moviment m) const;
        //Pre: Parametres del Vehicle v, files i cols entrats correctament. Post: Retorna true si no hi ha cap altre vehicle bloquegi el despla├žament. Si n'hi ha algun retorna false.
        void mostrar() const;
        //Pre: Tauler ple. Post: Mostra per pantalla totes les posicions del tauler amb els vehicles.

        // MODIFICADORS
        void posarVehicle(char a, Vehicle v);
        //Pre: a correcte i Vehicle v valid. Post: Coloca el vehicle del puzzle al Tauler al lloc que li toca.
        void processar(Vehicle v, int cont);
        //Pre: Vehicle v valid i cont>=0. Post: Assigna una lletra al vehicle i si es el primer horitzontal guarda la fila com a fila de surtida.
        bool validarMov(Moviment m);
        //Pre: --; Post: Retorna false si la lletra no es de cap Vehicle del taulell, o si el moviment no es pot fer, altrament retorna true.
        void ferMov(pilaMoviments pilaMovs, Moviment m);
        //Pre: Parametres lletra, files i cols correctes. Post: Mou el vehicle que tingui la lletra entrada les files i columnes que ens entren i empila el moviment a la pila.
        void desferMov(pilaMoviments pilaMovs);
        //Pre: Movimetns de la pila >0. (No es pot desfer moviments si no n'hi ha cap). Post: Desfa l'ultim moviment i el desempila de la Pila de moviments.
        bool movPossible(Vehicle v, int files, int cols);

    private:
        // TAULA DE VEHICLES
        Vehicle * a_v;
        int a_valids;

        // ATRIBUTS
        pilaMoviments a_pila;
        int a_f;
        int a_n;
        int a_surt;
        char ** a_mp;

        // METODES
        void alliberarMemoria();
        void reservarMemoria();
        void copiar(const Tauler &t);
};

#endif // TAULER_H

When I start it, it asks for a puzzle as it should, but then it crashes in this line:

a_mp[i][j]=t.a_mp[i][j];

In the 'copiar' method. What I undertand is that I'm giving a_mp[i][j] a value that I don't know, but I don't know how to fix it, any ideas? I know the names aren't in English but I hope this isn't a problem.

Thanks a lot EDIT: Deleted iniciar(), it wasn't the cause of the problem

Answers


It looks like operator= starts by freeing current memory (ok), allocating memory (but how much should be allocated?) and copy.

If the source size is bigger than destination size you are going to overwrite memory that was not allocated.

Before calling the memory allocator you should first set a_f and a_n to the correct values.


I think you made a mistake here:

Tauler& Tauler::operator=(const Tauler& y) {
if (this!=&y) {
    alliberarMemoria();
    reservarMemoria();
>>     y.iniciar();
    copiar(y);
}

If an instance of your object has a a_f that's less than y.a_f then when you're copying the y you're writing to places that's not allocated. You probably want to do iniciar(), and not y.iniciar().

I might be wrong, since you haven't posted iniciar() source code.


Need Your Help

git difftool to give directory compare?

git diff beyondcompare

Is it possible to get the git difftool command to open a directory compare between the changed files and the staging/checked files?