Reputation: 21
I have written a basic data structure to solve a recursion problem in C. I don't understand why in one particular case I get a segmentation fault, even if in the other cases seems to work just fine. Here's just the main part of the code: if you have the patience, here's the full code.
typedef struct{
char color;
int val;
}pipe;
typedef struct _tile tile;
struct _tile{
pipe pipe1;
pipe pipe2;
int inUse;
};
typedef struct{
tile *theTiles;
tile *possibleTiles;
int tileNum;
int numInUse;
}tileCollection;
typedef struct{
tile *tilePointer;
int rotation;
}box;
typedef struct{
box **board;
box **solMax;
int nCol;
int nRow;
}boardWrap;
void findMax(boardWrap *theBoardWrap, tileCollection *theTileColl, int col, int row){
if(col == (theBoardWrap->nCol-1)){//se sono arrivato alla fine della riga
if(row == (theBoardWrap->nRow -1)){//sono arrivato alla fine della scacchiera
if(evaluateScore(theBoardWrap)){// se la soluzione è massima
theBoardWrap->solMax = theBoardWrap->board; // copio la soluzione max
}
return;
}
findMax(theBoardWrap, theTileColl, 0, row+1);//ricorro sulla riga successiva, alla prima colonna
}
if(theBoardWrap->board[col][row].tilePointer != NULL){//se la casella è già occupata
findMax(theBoardWrap, theTileColl, col+1, row); //ricorro sulla colonna successiva
}
else{//se la casella è vuota
for(int i = 0; i < (theTileColl->tileNum * 2); i++){//ciclo che scorre tutte le possibili piastrelle inseribili
if(theTileColl->possibleTiles[i].inUse == 0){//controllo se la posso mettere
theTileColl->possibleTiles[i].inUse = 1;//la marco come inserita
//inserimento piastrella
theBoardWrap->board[col][row].tilePointer = &theTileColl->possibleTiles[i];//inserisco la piastrella
findMax(theBoardWrap, theTileColl, col+1, row);//ricorro sulla colonna successiva
theTileColl->possibleTiles[i].inUse = 0;//BACKTRACK
}
}
}
}
int evaluateScore(boardWrap *theBoardWrap){//ritorna '1' se il valore attuale è maggiore del Max passato, '0' se non è così
int scoreBoard1, scoreBoardMax;
scoreBoardMax = boardScoreCalc(theBoardWrap, theBoardWrap->solMax);
scoreBoard1 = boardScoreCalc(theBoardWrap, theBoardWrap->board);
if(scoreBoard1 > scoreBoardMax) {
return 1;
}
else
return 0;
}
int boardScoreCalc(boardWrap *theBoardWrap, box **board){//se passo la la board by reference ho un SIGSEGV, se la passo by value no
int flagRowColor = 0, flagColColor = 0;
int totScoreRow = 0;
int totScoreCol = 0;
int rowPoints[theBoardWrap->nRow], colPoints[theBoardWrap->nCol];
for(int i = 0; i < theBoardWrap->nRow; i++){
for(int j = 0; j < theBoardWrap->nCol; j++){
//calcolo il punteggio per la riga
if(j == 0){//inizio riga
rowPoints[i] = board[i][j].tilePointer->pipe1.val;
flagRowColor = 1;
}
else if(matchColor(theBoardWrap->board[i][j].tilePointer->pipe1.color,theBoardWrap->board[i][j-1].tilePointer->pipe1.color) && flagRowColor){
rowPoints[i] += board[i][j].tilePointer->pipe1.val;
}
else{
rowPoints[i] = 0;
flagRowColor = 0;
}
//calcolo il punteggio per le colonne
if(i == 0){//inizio colonna
colPoints[j] = board[i][j].tilePointer->pipe2.val;
flagColColor = 1;
}
else if(matchColor(theBoardWrap->board[i][j].tilePointer->pipe1.color,theBoardWrap->board[i-1][j].tilePointer->pipe1.color) && flagColColor){//HERE I GET SEGSIGV
colPoints[j] += board[i][j].tilePointer->pipe2.val;
}
else {
colPoints[j] = 0;
flagColColor = 0;
}
}
}
for(int i = 0; i < theBoardWrap->nRow; i++){
totScoreRow += rowPoints[i];
}
for(int j = 0; j < theBoardWrap->nCol; j++){
totScoreCol *= colPoints[j];
}
return totScoreCol + totScoreRow;
}
Upvotes: 2
Views: 86
Reputation: 193
I launched your program with your input data. No matter your program crashes because of absent input files. But according to GDB output your program does not fill theBoardWrap->board[2][0].tilePointer
field at line 241 and tries to dereference it. My advice is to learn to use debugger (like GDB), to use assertions from <assert.h>
, to handle manually allocated memory very accurately, to perform at least comparison to NULL
pointer, like this:
assert(theBoardWrap != NULL);
assert(theBoardWrap->board[i][j].tilePointer != NULL);
assert(theBoardWrap->board[i-1][j].tilePointer != NULL);
And no, it is definitely not a stack overflow.
Upvotes: 1