PDA

Ver la versión completa : C++ ¡¡Ayuda a un novato!! Violación de segmento ('core' generado)



Daniel A.
25/02/2016, 10:44
Hola buenas! Es la primera vez que pregunto algo como "programador" en este foro xD. Soy un completo principiante y llevo pocos meses programando. Mi pregunta es sobre el siguiente módulo de mi programa:

bool addFighter(Ship &ship)
{

char op[3];
int num, cod, i, j, pos;
bool salida;
salida=false;
cout<<"Enter fighter type (tf/tb/ti/ta):";
cin.getline(op,3);
cod=5;


for(i=0; i<MAXFIGHTERS/2; i++){
if(op==FIGHTERABR[i])
cod=i;
}

if(cod>=MAXFIGHTERS/2)
error(WRONG_FIGHTER_TYPE);
else{
cout<<"Number of fighters:";
cin>>num;
if(num*FIGHTERTABLE[cod].cost > ship.credits)
error(NO_FUNDS);
else if(ship.fighters.size()+num>IMPSHIPCAPACITY)
error(CAPACITY_EXCEEDED);
else{
for(j=0; j<num; j++){
pos=ship.fighters.size() + j;
ship.fighters[pos] = FIGHTERTABLE[cod];
ship.credits = ship.credits-FIGHTERTABLE[cod].cost;
salida=true;

}

}


}
return salida;
}
Lo que debe hacer este módulo es agregar en la última posición del vector ship.fighters un nuevo caza de combate si se cumple que hay suficiente espacio (definido por IMPSHIPCAPACITY) y se tienen suficientes fondos para pagarlo(ship.credits). Tras compilar y ejecutar los tres casos de error funcionan perfectamente (wrong fighter type, capacity exceeded y no funds) pero si introduzco datos validos me salta lo de "Violación de segmento ('core' generado)". Puede alguno de vosotros ver el por que?
Adjunto el código completo también:
#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

typedef struct {
string type; // TIE Fighter, X-Wing, ...
int velocity;
int attack; // attack power
int shield; // current shield status. if <=0, the fighter is considered destroyed
int cost; // cost in credits
} Fighter;


typedef struct {
bool side; // IMPERIAL or REBEL
int maxCapacity; // maximum capacity of fighters allowed in the ship
int credits; // credits remaining to buy fighters, make repairs or improvements
int wins; // enemy fighters destroyed
int losses; // fighters lost
vector<Fighter> fighters; // fighters inside the ship
} Ship;


// Fighters table

const int MAXFIGHTERS=8;

// abbreviations (to use in option "Add fighter")
const string FIGHTERABR[]= { "tf", "tb", "ti", "ta",
"xw", "yw", "aw", "bw"
};

const Fighter FIGHTERTABLE[] = { //Tabla de los posibles cazas que se pueden utilizar
{ "TIE-Fighter", 150, 75, 30, 45 },
{ "TIE-Bomber", 80, 150, 45, 75 },
{ "TIE-Interceptor", 180, 65, 30, 55 },
{ "TIE-Advanced", 160, 80, 90, 95 },
{ "X-Wing", 175, 90, 75, 65 },
{ "Y-Wing", 90, 150, 90, 90 },
{ "A-Wing", 200, 60, 50, 45 },
{ "B-Wing", 120, 200, 90, 100 }
};


// ship constants
const bool IMPERIAL=false;
const bool REBEL=true;

const int IMPSHIPCAPACITY=30;
const int REBSHIPCAPACITY=35;

const int initialImperialShipDotation[] = {10,5,5,5,0,0,0,0};
// 10 TIE-Fighters, 5 TIE-Bombers, 5 TIE-Interceptors, 5 TIE-Advanced, 0 X-Wing, ....

const int initialRebelShipDotation[] = {0,0,0,0,10,5,8,5};
// 0 TIE-Fighters ..., 10 X-Wing, 5 Y-Wing, 8 A-Wing, 5 B-Wing

// ship initial credits
const int CREDITS_INITIAL=2000;

// error numbers
const int UNKNOWN_OPTION=1;
const int WRONG_FIGHTER_TYPE=2;
const int CAPACITY_EXCEEDED=3;
const int WRONG_NUMBER=4;
const int NO_FUNDS=5;
const int NO_FIGHTERS=6;

//---------------------------------------------------
void error(int n)
{
cout << "ERROR (" << n << "): " ;

switch (n)
{
case UNKNOWN_OPTION:
cout << "unknown option" << endl;
break;
case WRONG_FIGHTER_TYPE:
cout << "wrong fighter type" << endl;
break;
case CAPACITY_EXCEEDED:
cout << "ship capactity exceeded" << endl;
break;
case WRONG_NUMBER:
cout << "wrong number" << endl;
break;
case NO_FUNDS:
cout << "not enough credits" << endl;
break;
case NO_FIGHTERS:
cout << "not enough fighters" << endl;
break;
}
}

//---------------------------------------------------
int getRandomNumber(int max)
{
// Genera un número aleatorio entre 0 y maximo-1
//
int na;

na = (int)(((double)max)*rand()/(RAND_MAX+1.0));
return na;
}


//---------------------------------------------------
void initializeShip(Ship &ship,bool side)
{
int i, j;


if(side==REBEL){
ship.side=REBEL;
ship.maxCapacity=REBSHIPCAPACITY;
ship.credits=CREDITS_INITIAL;
ship.wins=0;
ship.losses=0;
for(i=0; i<MAXFIGHTERS; i++){
if(initialRebelShipDotation[i]!=0)
for(j=0; j<initialRebelShipDotation[i]; j++){
ship.fighters.push_back(FIGHTERTABLE[i]);

}
}
}else{
ship.side=IMPERIAL;
ship.maxCapacity=IMPSHIPCAPACITY;
ship.credits=CREDITS_INITIAL;
ship.wins=0;
ship.losses=0;
for(i=0; i<MAXFIGHTERS; i++){
if(initialImperialShipDotation[i]!=0)
for(j=0; j<initialImperialShipDotation[i]; j++){
ship.fighters.push_back(FIGHTERTABLE[i]);

}

}
}
}


//---------------------------------------------------
void listFighter(const Fighter &f)//Saca a pantalla las características de un único caza
{
cout<<f.type<<"(v="<<f.velocity<<", a="<<f.attack<<", s="<<f.shield<<", c="<<f.cost<<")"<<endl;

}

void listFighters(const vector<Fighter> &vf) //Este módulo convierte los resultados individuales que desarolla el módulo anterior en una lista numerada
{
int unsigned i;
for(i=0; i<vf.size(); i++){ //Recordar que vector.size() da el TAMAÑO del vector; no la POSICIÓN final (Esta nota es para mí, supongo que el que lea esto ya lo sabrá)
cout<<"["<<i+1<<"] ";
listFighter(vf[i]);
}
}

void listShip(const Ship &ship)
{
cout<<"Ship info: max. capacity="<<ship.maxCapacity<<", side="<<ship.side<<", credits="<<ship.credits<<", wins="<<ship.wins<<", losses="<<ship.losses<<endl;
listFighters(ship.fighters);
}
bool addFighter(Ship &ship)
{

char op[3];
int num, cod, i, j, pos;
bool salida;
salida=false;
cout<<"Enter fighter type (tf/tb/ti/ta):";
cin.getline(op,3);
cod=5;


for(i=0; i<MAXFIGHTERS/2; i++){
if(op==FIGHTERABR[i])
cod=i;
}

if(cod>=MAXFIGHTERS/2)
error(WRONG_FIGHTER_TYPE);
else{
cout<<"Number of fighters:";
cin>>num;
if(num*FIGHTERTABLE[cod].cost > ship.credits)
error(NO_FUNDS);
else if(ship.fighters.size()+num>IMPSHIPCAPACITY)
error(CAPACITY_EXCEEDED);
else{
for(j=0; j<num; j++){
pos=ship.fighters.size() + j;
ship.fighters[pos] = FIGHTERTABLE[cod];
ship.credits = ship.credits-FIGHTERTABLE[cod].cost;
salida=true;

}

}


}
return salida;
}
int main(int argc,char *argv[])
{
Ship imperialDestroyer, rebelShip;

bool side;

srand(1); // inicializar secuencia de números aleatorios: NO TOCAR
side=REBEL;
initializeShip(rebelShip, side);
side=IMPERIAL;
initializeShip(imperialDestroyer, side);


listShip(imperialDestroyer);
listShip(rebelShip);
side=addFighter(imperialDestroyer);
}


Edit: Ufff... perdonad que no haya nigún tipo de sangrado, ha desaparecido en el copia y pega

Ñuño Martínez
25/02/2016, 11:00
Puede haber chorrocientasmil razones y media.

Te recomiendo que lo ejecutes con un depurador (GDB, por ejemplo), a ver dónde falla exactamente y tirar desde allí.

juanvvc
25/02/2016, 11:06
En una ullada rápida, estas línes de código no me gustan nada:



for(j=0; j<num; j++){
pos=ship.fighters.size() + j;
ship.fighters[pos] = FIGHTERTABLE[cod];
....
}


Con esas líneas accedes sí o sí fuera del vector de fighters, ¿no? Porque pos va a ser siempre mayor que fighters.length()

Daniel A.
25/02/2016, 11:17
En una ullada rápida, estas línes de código no me gustan nada:



for(j=0; j<num; j++){
pos=ship.fighters.size() + j;
ship.fighters[pos] = FIGHTERTABLE[cod];
....
}


Con esas líneas accedes sí o sí fuera del vector de fighters, ¿no? Porque pos va a ser siempre mayor que fighters.length()

Solucionado. Muchisimas gracias.

for(j=0; j<num; j++){

ship.fighters.push_back(FIGHTERTABLE[cod]);
ship.credits = ship.credits-FIGHTERTABLE[cod].cost;
salida=true;

}
Que encima ya tenia la solución delante de las narices porque había utilizado la función push_back en el módulo initialiceShip, manda huevos

kiwoore
25/02/2016, 13:34
Para la próxima, te recomiendo que en estos casos uses valgrind o sucedáneos.
Un saludo!

swapd0
03/03/2016, 21:49
¿Por que hay constantes que tienen un guion entre cada palabra y otras no? Intenta ser mas uniforme con estas cosas.