I'm trying to practice C by writing a memory-type card game. The game is compiled by gcc on ARMv8. The user enters a number "users_N" in the argument line and a board of cards is created size: 2N x 2N.
The program runs just fine when the number is 1 or 2. But if it's 3 or bigger, I get a segmentation fault when trying to initialize the board. I thought this meant it was a stack overflow, but I increased the stack size to unlimited on my SSH and the problem was not resolved. I don't think it's a problem with pointers or trying to access an array out-of-bounds either, as it runs just fine until after 10 cards are added to the array.
The print statements are just to determine exactly when the segfault occurs.See image of for loop segfault
EDIT: to add more context... I know it's a bit messy, sorry!
int main(int argc, char *argv[]) {
if (argc < 3){ //Checking user's command line input.
printf("Missing argument. Exiting... \n");
return 0;
}
users_N = atoi(argv[2]);
srand(time(NULL)); //Initialize random number generator.
int ***board = (int ***)malloc(2 * users_N * sizeof(int)); //Dynamic array to store the board values
for (int i = 0; i < 2 * users_N; i++){
board[i] = (int **)malloc(2 * users_N * sizeof(int)); /*Array of pointers (rows) filled with
an array (columns). */
for (int j = 0; j < 2 * users_N; j++){
board[i][j] = (int *)malloc(2 * sizeof(int)); //3rd dimension to show/hide cards.
}
}
initialize(board);
}
/*
* Function initialize sets up the board. It takes the 3D board array. A card deck is created the
* size of 2N^2, then shuffled and added to the board. The 3rd dimension is initialized
* completely to 1, so all cards are shown. There is no return.
*/
void initialize(int*** board){
int* cards = (int *)malloc(2 * users_N * users_N * sizeof(int)); //Create an array of cards.
printf("Cards created\n");
for (int c = 0; c < (2 * users_N * users_N); c++){
printf("card: %d\n",c);
cards[c]=c;
}
int half = 0;
while (half < 2){ //Divide up into 2 halves of the board, to repeat shuffle and card placement.
shuffle(cards);
int cardsNum = 0;
for (int j = 0; j < users_N; j++){ //For each row in the current half:
printf("\n row = %d ", j);
for (int k = 0; k < (users_N * 2); k++){ //For each column:
printf("col = %d ",k);
board[j + (half * users_N)][k][0] = cards[cardsNum]; /* Assign appropriate
card to each board
position. */
printf("set to: %d ", board[j + (half * users_N)][k][0]);
board[j + (half * users_N)][k][1] = 1;
cardsNum++;
printf("Card num: %d \n", cardsNum);
}
}
half++; //Moves to next half to repeat.
}
}
/*
* Function shuffle takes the array of cards as a parameter. It will then randomly mix array.
* Numbers are not repeated and will not exceed 2N*N-1. No return values.
*/
void shuffle(int *cards){
int j;
for (int k = 0; k < (2 * users_N * users_N) - 2; k++){
j = randomNum(k, (2 * users_N * users_N) - 1); //Assign a random number between k and 2N*N-1.
swap(cards, k, j);
printf("cards swapped: %d,%d\n",k,j);
}
}
/*
* Function swap takes the array of cards, two index integers. The index integers indicate the positions of
* the elements (cards) to switch. No return values.
*/
void swap(int *cards, int i, int j){
int temp = cards[i]; //Value of position i stored in temp.
cards[i] = cards[j]; //value of card j assigned to card i.
cards[j] = temp; //Value of temp assigned to card j.
}
Allocation of your board is wrong:
int ***board = (int ***)malloc(2 * users_N * sizeof(int));
^^^^^^^^^^^
wrong size
for (int i = 0; i < 2 * users_N; i++){
board[i] = (int **)malloc(2 * users_N * sizeof(int));
^^^^^^^^^^^
wrong size
...
}
When you have board
as int ***
you don't want size of int
during first allocation. You want size of int **
. Like
int ***board = malloc(2 * users_N * sizeof(int**));
A better approach is to use the variable name - like:
int ***board = malloc(2 * users_N * sizeof *board);
^^^^^^
Better approach
to get correct size
The same applies to the next malloc