我遇到矩阵问题,问题是当我尝试复制它时,它给出了错误'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(),这不是问题的原因
答案 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_f
和a_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)。也许如果你很幸运并且失败很简单,你可以通过前提条件断言,例如我建议的那些断言。