复制矩阵时c ++分段错误

时间:2013-05-02 12:02:35

标签: c++ class matrix segmentation-fault

我遇到矩阵问题,问题是当我尝试复制它时,它给出了错误'Segmentation Fault'。这是涉及的代码:

的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

当我开始它时,它会要求一个谜题,但它会在这一行崩溃:

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

在'copiar'方法中。我所承诺的是,我给a_mp [i] [j]一个我不知道的价值,但我不知道如何解决它,任何想法? 我知道名字不是英文,但我希望这不是问题。

非常感谢 编辑:已删除iniciar(),这不是问题的原因

3 个答案:

答案 0 :(得分:3)

我认为你在这里犯了一个错误:

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

如果对象的实例的a_f小于y.a_f,那么当你复制y时,你正在写入未分配的地方。 你可能想做iniciar(),而不是y.iniciar()。

我可能错了,因为你还没有发布iniciar()源代码。

答案 1 :(得分:2)

看起来operator=首先释放当前内存(ok),分配内存(但应该分配多少?)并复制。

如果源大小大于目标大小,则将覆盖未分配的内存。

在调用内存分配器之前,您应首先将a_fa_n设置为正确的值。

答案 2 :(得分:1)

不是答案,而是一些建议来找到它。

首先,在代码中隔离读取值并写入另一个矩阵,即将查询与命令隔离。

而不是

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

写:

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

其次,assert所有数组间接都在它们的极限之间。

assert(0 <= i);
assert(i <= SOME_MAXIMUM_VALUE_FOR_I);
assert(0 <= j);
assert(j <= SOME_MAXIMUM_VALUE_FOR_J);
int valorAAssignar = t.a_mp[i][j];
a_mp[i][j] = valorAAssignar;

在存在数组间接的所有其他点处执行相同操作。实际上,你最好写一个方法,如ReadCellValue,或加泰罗尼亚语LlegeixValor

   LlegeixValor(a_mp, i, j);

基本上我做了以上建议:检查限制并返回值。

如果在调试模式下运行它,你应该找到出错的地方,其中检查断言。通过编写assert(false);并确定它失败,确保最后一点。然后删除这一行。

此代码要求添加前置条件,后置条件和类不变量(请参阅Design by Contract)。也许如果你很幸运并且失败很简单,你可以通过前提条件断言,例如我建议的那些断言。