utente78dh
utente78dh

Reputation: 21

SIGSEGV accessing parameters of a structure in C

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

Answers (1)

Northsoft
Northsoft

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

Related Questions