So I have created and allocated memory for a double pointer using the following function:
void mallocDoubleArr(double ***arr, int size)
{
printf("Here: %d", size);
int i, j;
*arr = malloc(size * sizeof(double*));
for(i = 0; i < size; i++)
{
(*arr)[i]= malloc(size*sizeof(double));
for (j = 0; j < size; j++)
{
(*arr)[i][j] = 0;
}
}
}
And I called the function using:
double **G; //Create double pointer to hold 2d matrix
mallocDoubleArr(&G, numNodes);
Now my question is how would I write a function to free the memory?
I tried something like this:
void freeDoubleArr(double ***arr, int size)
{
int i, j;
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
free((arr)[i]);
free(arr);
}
It seems that you want to pass the address of a pointer to your freeDoubleArr like freeDoubleArr(&G, numnodes) (which I would rather call deleteDoubleArr). Then you need to have
void freeDoubleArr(double ***arrptr, int size)
{
double** arr = *arrptr;
for (int i = 0; i < size; i++)
free(arr[i]);
free (arr);
*arrptr = NULL;
}
However, you could decide that your square matrix is not represented as an array of pointers to arrays, but just as a plain array. Perhaps using flexible array members (of C99 and later) like
struct matrix_st {
unsigned size;
double arr[]; /* flexible array of size*size elements */
};
could be useful, with the convention that arr is really an array of size*size elements (each being a double).
Then you can define quick access and mutator inline functions.
inline double get_element(struct matrix_st *m, int i, int j) {
assert (m != NULL);
unsigned s = m->size;
assert (i>=0 && i<s && j>=0 && j<s);
return m->arr[s*i+j];
}
inline void put_element(struct matrix_st* m, int i, int j, double x) {
assert (m != NULL);
unsigned s = m->size;
assert (i>=0 && i<s && j>=0 && j<s);
m->arr[i*s+j] = x;
}
When optimizing and with <assert.h> (see assert(3) ...) and compiling with -DNDEBUG the above accessor get_element and mutator put_element would be perhaps faster than your code.
And the matrix creation is just (to create a zero-ed matrix):
struct matrix_st* make_matrix (unsigned size) {
struct matrix_st* m = malloc(sizeof (struct matrix_st)
+ size*size*sizeof(double);
if (!m) { perror("malloc"); exit(EXIT_FAILURE); };
m->size = size;
memset(m->arr, 0, sizeof(double)*size*size);
return m;
}
Then the user could just use one single call to free to free such a matrix.
BTW, if coding on Linux, compile with gcc -Wall -g and use valgrind memory leak detector and gdb debugger.
Shouldn't your free code be more like the following:
void freeDoubleArr(double ***arr, int size)
{
int i;
for (i = 0; i < size; i++)
free((*arr)[i]);
free(*arr);
}
You're not even using the 'j' parameter anywhere so the inner for loop is going to cause it to attempt to free the same area of memory size times. You also need to dereference the pointer that's passed in to get to the one that's malloc'd, in the same way you do when assigning to result of malloc into it.
Also, it would be useful when saying something doesn't work to include what specific errors you are seeing or what makes you think it isn't working properly.
Related
Related to dynamic allocation inside a function, most questions & answers are based on double pointers.
But I was recommended to avoid using double pointer unless I have to, so I want to allocate a 'array pointer' (not 'array of pointer') and hide it inside a function.
int (*arr1d) = calloc(dim1, sizeof(*arr1d));
int (*arr2d)[dim2] = calloc(dim1, sizeof(*arr2d));
Since the above lines are the typical dynamic-allocation of pointer of array, I tried the following.
#include <stdio.h>
#include <stdlib.h>
int allocateArray1D(int n, int **arr) {
*arr = calloc(n, sizeof(*arr));
for (int i = 0; i < n; i++) {
(*arr)[i] = i;
}
return 0;
}
int allocateArray2D(int nx, int ny, int *(*arr)[ny]) {
*arr[ny] = calloc(nx, sizeof(*arr));
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
int main() {
int nx = 3;
int ny = 2;
int *arr1d = NULL; // (1)
allocateArray1D(nx, &arr1d);
int(*arr2d)[ny] = NULL; // (2)
allocateArray2D(nx, ny, &arr2d);
for (int i = 0; i < nx; i++) {
printf("arr1d[%d] = %d \n", i, arr1d[i]);
}
printf("\n");
printf("arr2d \n");
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
printf(" %d ", arr2d[i][j]);
}
printf("\n");
}
return 0;
}
And the error message already comes during the compilation.
03.c(32): warning #167: argument of type "int (**)[ny]" is incompatible with parameter of type "int *(*)[*]"
allocateArray2D(nx, ny, &arr2d);
^
It is evident from the error message that it has been messed up with the argument types (that I wrote as int *(*arr)[ny]) but what should I have to put there? I tried some variants like int *((*arr)[ny]), but didn't work).
And if I remove the 2D parts, then the code well compiles, and run as expected. But I wonder if this is the right practice, at least for 1D case since there are many examples where the code behaves as expected, but in fact there were wrong or un-standard lines.
Also, the above code is not satisfactory in the first place. I want to even remove the lines in main() that I marked as (1) and (2).
So in the end I want a code something like this, but all with the 'array pointers'.
int **arr2d;
allocateArray2D(nx, ny, arr2d);
How could this be done?
You need to pass the array pointer by reference (not pass an array pointer to an array of int*):
int *(*arr)[ny] -> int (**arr)[ny]
The function becomes:
int allocateArray2D(int nx, int ny, int (**arr)[ny]) {
*arr = calloc(nx, sizeof(int[ny])); // or sizeof(**arr)
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
For details, check out Correctly allocating multi-dimensional arrays
Best practices with malloc family is to always check if allocation succeeded and always free() at the end of the program.
As a micro-optimization, I'd rather recommend to use *arr = malloc( sizeof(int[nx][ny]) );, since calloc just creates pointless overhead bloat in the form of zero initialization. There's no use of it here since every item is assigned explicitly anyway.
Wrong parameter type
Strange allocation
Wrong size type
I would return the array as void * too (at least to check if allocation did not fail).
void *allocateArray2D(size_t nx, size_t ny, int (**arr)[ny]) {
//*arr = calloc(nx, sizeof(**arr)); calloc is not needed here as you assign values to the array
*arr = malloc(nx * sizeof(**arr));
for (size_t i = 0; i < nx; i++) {
for (size_t j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return *arr;
}
Okey, so I need to dynamically allocate a matrix in C and then pass it to be modified in a function (I want the changes that I make inside the function to remain after I return to main). This is what i did:
void read_zone (int *(**m), int N, int M) {
int x, i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
scanf("%d", &x);
m[i][j] = x;
}
}
And then inside main() I have:
int **m;
int N = 2, M = 3;
m = (int **) malloc(N * sizeof(int *));
for (i = 0; i < N; i++) {
m[i] = (int *) malloc(M * sizeof(int));
}
read_zone(&m, N, M);
So the problem is that when it enters the function it seems that m[0][2] is not allocated (even though m[0][0] and m[0][1] are), but in main I can access it, so it's definitely caused by the way I pass it to the function (&m).
What's the right way to do it?
You will have to dereference it first like this because then you get the double pointer to which you have allocated the memory dynamically
(*m)[i][j] = x;
Also don't cast the return value of malloc.
In fact passing the address of m here is redundant in the very first place. You can simply do this
read_zone(m, N, M);
And
void read_zone (int **m, int N, int M) {
..
scanf("%d", &x);
m[i][j] = x;
..
}
The thing is here passing the address of the variable won't serve you any purpose. You are not changing the value of the double pointer.
If you have compiled your code - you will see that compiler complained about type mismatch. Function signature would be
void read_zone (int ***m, int N, int M) (The way you did)
Check the return value of malloc , scanf to know whether if the call to them were successful or not.
Free the dynamically allocated memory when you are done working with it.
Compile code with all flags enabled gcc -Wall -Werror progname.c.(Using gcc).
What is the best way to return a multidimensional array from a function in c ?
Say we need to generate a multidimensional array in a function and call it in main, is it best to wrap it in a struct or just return a pointer to memory on the heap ?
int *create_array(int rows, int columns){
int array[rows][columns] = {0};
return array;
}
int main(){
int row = 10;
int columns = 2;
create_array(row,columns);
}
The code above, is just to sketch out the basic program I have in mind.
This is wrong:
int *create_array(int rows, int columns){
int array[rows][columns] = {0};
return array;
}
and should produce a warning like this:
prog.c:2:6: note: (near initialization for 'array')
prog.c:3:13: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
return array;
^~~~~
prog.c:3:13: warning: function returns address of local variable [-Wreturn-local-addr]
since you are returning the address of an automatic variable; its lifetime ends when its corresponding function terminates.
You should either declare a double pointer in main(), pass it through the function, dynamically allocate memory for it and return that pointer. Or you could create the array in main() and pass the double pointer to the function.
I want to know ways to allocate multidimensional arrays on the heap and pass them around
For allocating memory on the heap you could use one of these two methods, which involve pointers:
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **array;
array = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
array[i] = malloc( M*sizeof(int) );
return array;
}
// We don't return the pointer
void getNoReturn(int*** array, int N, int M) {
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
*array = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
(*array)[i] = malloc( M*sizeof(int) );
}
void fill(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
p[i][j] = j;
}
void print(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
printf("array[%d][%d] = %d\n", i, j, p[i][j]);
}
void freeArray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
int **p;
//getNoReturn(&p, 2, 5);
p = get(2, 5);
fill(p ,2, 5);
print(p, 2, 5);
freeArray(p ,2);
return 0;
}
Pick whichever suits best your style.
What is the best way to return a multidimensional array from a function in c ?
My recommendation is to avoid doing that, and avoid multidimensional arrays in C (they are unreadable and troublesome).
I would recommend making your matrix type your proper abstract data type, represented by some struct ending with a flexible array member:
struct mymatrix_st {
unsigned nbrows, nbcolumns;
int values[];
};
Here is the creation function (returning a properly initialized pointer to dynamic memory):
struct mymatrix_st*
create_matrix(unsigned mnbrows, unsigned mnbcolumns) {
if (mnbrows > UINT_MAX/4 || mnbcolumns > UINT_MAX/4
||(unsigned long)mnbrows * (unsigned long)mnbcolums
> UINT_MAX) {
fprintf(stderr, "too big matrix\n");
exit(EXIT_FAILURE);
};
size_t sz = sizeof(struct mymatrix_st)+(mnbrows*mnbcolumns*sizeof(int));
struct mymatrix_st*m = malloc(sz);
if (!m) {
perror("malloc mymatrix"); exit(EXIT_FAILURE); };
m->nbrows = mnbrows;
m->nbcolumns = mnbcolumns;
for (unsigned long ix=(unsigned long)mnbrows * (unsigned long)mnbcolumns-1;
ix>=0; ix--)
m->values[ix] = 0;
return m;;
} /*end create_matrix*/
It is on purpose that struct mymatrix_st don't contain any interior pointer. You can and should use free to destroy it.
Here is the accessor function; make it a static inline function and define it in the same header declaring struct mymatrix_st and create_matrix, e.g.
static inline int getmatrix(struct mymatrix_st*m, unsigned row, unsigned col) {
if (!m) {
fprintf(stderr, "getmatrix with no matrix\n");
exit(EXIT_FAILURE);
};
if (row >= m->nbrows || col >= m->nbcolumns){
fprintf(stderr, "getmatrix out of bounds\n");
exit(EXIT_FAILURE);
};
return m->values[row*m->nbcolumns + col];
}
I leave up to you to define and implement the other operations on your abstract struct mymatrix_st type.
(you could adapt the code, perhaps removing the out of bound check, but I don't recommend unsafe code)
int** create_array(int rows, int columns){
int** array = malloc(rows * sizeof(int*));
int i;
for (i=0; i<rows; i++)
array[i] = malloc(columns * sizeof(int));
return array;
}
should do the trick. If you use int array[rows][columns]; then it's dead as soon as the functiom returns, and you get a UB. You should at least use dynamic memory allocation.
You can't return an array, but you can return a regular pointer and document that the callee may treat it as a pointer to a multidimensional array of the dimensions that it had passed to the caller.
(Note that the returned pointer must point to dynamic or static, but not automatic memory--don't return pointers to local variables!)
It takes some slightly wordy casts and possibly a macro but it's doable:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void*
multi(int R, int C)
{
return calloc ( 1, sizeof(int[R][C]) ); //or sizeof(int)*R*C
}
int main()
{
int (*r_)[3][4] = multi(3,4);
if(!r_) return EXIT_FAILURE;
#define r (*r_)
//emulate C++ a reference -- r now behaves as an `int r[3][4];`
//Test that addresses advance as they would in a multi-d array
int local[3][4];
assert(&local[1][0]-&local[0][0] == 4); //base example
assert(&r[1][0]-&r[0][0] == 4); //"returned" multi-d array
free(r); //or free(&r) or free(r_) -- here it shouldn't matter
#undef r
return 0;
}
Note that an array of pointers is not the same thing as a multi-d array.
A true multi-d array is one contiguous block, whereas an array of pointers (though usable with the same indexing syntax) has much worse locality of reference, so this might be preferable over returning pointers to pointers if you want better performance.
I'm trying to generate a matrix of some arbitrary dimensions. I can do it just fine by calling scanf in main and then assigning matrix elements on a row by row basis, but trying to do it in a single function, outside of main, (and only if scanf() is called outside of main) gives me a segfault error:
int **genmat(int nrow, int ncol){
int i,j;
int **mat = (int**) malloc(sizeof(int)*ncol*nrow);
char rowbuff[16];
for(i=0; i < nrow; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != ncol){
printf("Error: Input must be string of length %d\n", ncol);
goto INPUT;
}
else{
for(j=0; j < ncol; j++){
if(rowbuff[j] == '1'){
mat[i][j] = 1;
}
else{
mat[i][j] = 0;
}
}
}
}
return(mat);
}
The following works just fine:
int *genrow(int ncol, char *rowbuff){
int i;
int *row = malloc(sizeof(int)*ncol);
for(i=0;i<ncol;i++){
row[i] = rowbuff[i]%2;
}
return(row);
}
with the following in my main function to call genrow() for each row of the matrix:
for(i=0; i < row; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != col){
printf("Error: Input must be string of length %d\n", col);
goto INPUT;
}
else{
int *newrow = genrow(col, rowbuff);
for(j=0; j < col; j++){
matrix[i][j] = newrow[j];
}
free(newrow);
newrow = NULL;
}
}
Why is the behavior different in these two contexts?
Dynamically allocated 2D arrays are unfortunately burdensome and ugly in C. To properly allocate one, it is very important that you do so with a single call to malloc, just as you tried to do. Otherwise it won't be a 2D array, but instead some segmented, slow look-up table.
However, the result of that malloc call will be a pointer to a 2D array, not a pointer-to-pointer. In fact, pointer-pointers have nothing to do with 2D arrays whatsoever - this is a widespread but incorrect belief.
What you should have done is this:
int (*mat)[nrow][ncol] = malloc( sizeof(int[nrow][ncol] );
This is an array pointer to a 2D array. This syntax is already a bit burdensome, but to make things worse, it is not easy to pass this array pointer back to main, because it is a local pointer variable. So you would need to use a pointer to an array pointer... and there's no pretty way to do that. It goes like this:
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
To ease usage a bit, you can create a temporary pointer to rows, which doesn't require multiple levels of indirection and is therefore much easier to work with:
int (*matrix)[ncol] = *mat[0]; // in the pointed-at 2D array, point at first row
for(size_t r=0; r<nrow; r++) // whatever you want to do with this matrix:
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1; // much more convenient syntax than (**mat)[r][c]
}
}
From main, you'll have to call the code like this:
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
Example:
#include <stdio.h>
#include <stdlib.h>
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
int (*matrix)[ncol] = *mat[0];
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1;
}
}
}
void printmat (size_t nrow, size_t ncol, int mat[nrow][ncol])
{
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
printf("%d ", mat[r][c]);
}
printf("\n");
}
}
int main (void)
{
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
printmat(row, col, *mat);
free(mat);
return 0;
}
Please note that real code needs to address the case where malloc returns NULL.
I assume the problems is withint **mat = (int**) malloc(sizeof(int)*ncol*nrow);
You are trying to allocate the a 2D array right? But this isn't the correct method to allocate the memory. You can't allocate the whole chunk of memory one short.
What you should be doing here is, allocate the memory for all the rows(basically pointer to store the column address) and then for columns
int **mat= (int **)malloc(nrow * sizeof(int *));
for (i=0; i<nrow; i++)
mat[i] = (int *)malloc(ncol * sizeof(int));
Refer this link for more info http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/
I need to allocate contiguous space for a 3D array. (EDIT:) I GUESS I SHOULD HAVE MADE THIS CLEAR IN THE FIRST PLACE but in the actual production code, I will not know the dimensions of the array until run time. I provided them as constants in my toy code below just to keep things simple. I know the potential problems of insisting on contiguous space, but I just have to have it. I have seen how to do this for a 2D array, but apparently I don't understand how to extend the pattern to 3D. When I call the function to free up the memory, free_3d_arr, I get an error:
lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated
Would appreciate it if anyone could tell me what the fix is. Code is here:
#include <stdio.h>
#include <stdlib.h>
int ***calloc_3d_arr(int sizes[3]){
int ***a;
int i,j;
a = calloc(sizes[0],sizeof(int**));
a[0] = calloc(sizes[0]*sizes[1],sizeof(int*));
a[0][0] = calloc(sizes[0]*sizes[1]*sizes[2],sizeof(int));
for (j=0; j<sizes[0]; j++) {
a[j] = (int**)(a[0][0]+sizes[1]*sizes[2]*j);
for (i=0; i<sizes[1]; i++) {
a[j][i] = (int*)(a[j]) + sizes[2]*i;
}
}
return a;
}
void free_3d_arr(int ***arr) {
printf("lowest lvl\n");
free(arr[0][0]);
printf("mid lvl\n");
free(arr[0]); // <--- This is a problem line, apparently.
printf("highest lvl\n");
free(arr);
}
int main() {
int ***a;
int sz[] = {5,4,3};
int i,j,k;
a = calloc_3d_arr(sz);
// do stuff with a
free_3d_arr(a);
}
Since you are using C, I would suggest that you use real multidimensional arrays:
int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a));
This allocates contiguous storage for your 3D array. Note that the sizes can be dynamic since C99. You access this array exactly as you would with your pointer arrays:
for(int i = 0; i < sz[0]; i++) {
for(int j = 0; j < sz[1]; j++) {
for(int k = 0; k < sz[2]; k++) {
a[i][j][k] = 42;
}
}
}
However, there are no pointer arrays under the hood, the indexing is done by the magic of pointer arithmetic and array-pointer-decay. And since a single calloc() was used to allocate the thing, a single free() suffices to get rid of it:
free(a); //that's it.
You can do something like this:
int ***allocateLinearMemory(int x, int y, int z)
{
int *p = (int*) malloc(x * y * z * sizeof(int));
int ***q = (int***) malloc(x * sizeof(int**));
for (int i = 0; i < x; i++)
{
q[i] = (int**) malloc(y * sizeof(int*));
for (int j = 0; j < y; j++)
{
int idx = x*j + x*y*i;
q[i][j] = &p[idx];
}
}
return q;
}
void deallocateLinearMemory(int x, int ***q)
{
free(q[0][0]);
for(int i = 0; i < x; i++)
{
free(q[i]);
}
free(q);
}
I use it and works fine.