I'm trying to use calloc on array inside a function but it doesn't work. When trying to debug I found that inside the function the pointer points to the allocated memory but when leaving the function it points to NULL again. Tried all kinds of variations but can't seem to find a solution.
This is my code:
int main(int argc, char *argv[]) {
int *rows = NULL, *solvedRows = NULL;
int **board = NULL, **solvedBoard = NULL;
allocateMemory(dim, &(*rows), &(*board));
allocateMemory(dim, &(*solvedRows), &(*solvedBoard));
}
void allocateMemory(int dim, int** rows, int*** board) {
rows = calloc(dim*dim,sizeof(int));
board = calloc(dim, sizeof(int*));
if (rows == NULL || board == NULL) {
printf("Error: calloc has failed\n");
exit(1);
}
}
Need help to understand what's wrong and how to fix it.
EDIT
I tried:
*rows = calloc(dim*dim,sizeof(int));
*board = calloc(dim, sizeof(int*));
Still have same problem.
Also tried:
allocateMemory(dim, &rows, &board);
for line 4 and (5 the same) and in doesn't compile with the error: "error: passing argument 2 of 'allocateMemory' from incompatible pointer type [-Werror=incompatible-pointer-types] allocateMemory(dim, &rows, &board); ^" error: passing argument 3 of 'allocateMemory' from incompatible pointer type [-Werror=incompatible-pointer-types] allocateMemory(dim, &rows, &board); ^
EDIT
For anyone who encounters this problem and checks this page, this last try is in fact correct, as Michael answered below. The errors are for a mistake in the corresponding header file, and were fixed when fixing the header file.
Let's focus on your rows
variable:
rows
is a pointer, which is a variable holding a memory address.
Now you want alocateMemory to write into rows
the address of a block of memory, to hold your data. Easy enough:
size_d dim = 10;
int* rows = 0;
rows = calloc(1, sizeof(int) * dim);
However, if you put this code into a function like
void allocateMemory(size_t dim, int* rows) {
rows = calloc(1, sizeof(int) * dim);
}
Now if you call this function like
int* actualRows = 0;
allocateMemory(3, actualRows);
The value of actualRows
(namely 0
) will be copied into a new variable rows
which you manipulate in allocateMemory
. When you write into rows, its value changes, but when allocateMemory
is left, rows
will be destroyed. Never will actualRows
be altered.
What you want is that allocateMemory
sets the value of actualRows
o a memory address. To do this, you have to provide allocateMemory
with the address of actualRows
like
allocateMemory(3, &actualRows);
&atualRows
is the memory address of actualRows
and its type is int**
(pointer to a pointer to int
).
Now you have to adapt the signature of allocateMemory
appropriately:
void allocateMemory(size_t dim, int** rows) {
rows = calloc(1, sizeof(int) * dim);
}
And, since rows now is a pointer and you want to change its target, you need to dereference it before assigning it:
*rows = calloc(1, sizeof(int) * dim);
Yielding all in all:
void allocateMemory(size_t dim, int** rows) {
*rows = calloc(1, sizeof(int) * dim);
}
...
int* actualRows = 0;
allocateMemory(3, &actualRows);
...
For your board
, its the same in principle. Try
#include <stdio.h>
#include <stdlib.h>
void allocateMemory(int dim, int** rows, int*** board) {
*rows = calloc(dim * dim,sizeof(int));
*board = calloc(dim, dim * sizeof(int*));
if (rows == NULL || board == NULL) {
printf("Error: calloc has failed\n");
}
for(size_t i = 0; i < dim; ++i) {
(*board)[i] = calloc(1, sizeof(int) * dim);
if ((*board)[i] == NULL) {
printf("Error: calloc has failed\n");
}
}
}
int main(int argc, char *argv[]) {
size_t dim = 10;
int *rows = NULL;
int **board = NULL;
allocateMemory(dim, &rows, &board);
rows[0] = 10;
rows[1] = 11;
for(size_t i = 0; i < dim; ++i) {
printf("%i ", rows[i]);
}
printf("\n\n\n");
board[0][0] = 11;
board[9][0] = 99;
board[9][9] = 101;
for(size_t i = 0; i < dim; ++i) {
for(size_t k = 0; k < dim; ++k) {
printf("%i ", board[i][k]);
}
printf("\n");
}
printf("\n");
for(size_t i = 0; i < dim; ++i) free(board[i]);
free(board);
free(rows);
}