I am a newbie to C programming (relearning it after a long time) . I am trying to dynamically allocate memory to a 2D array using malloc. I have tried following the answers on stackoverflow like this and this. But I still get the segmentation fault.
My code is as below
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
void allocate2DArray(int **subset, int a, int b)
{
subset = (int **)malloc( a * sizeof(int *));
int i,j;
for(i = 0 ; i < a ; i++)
subset[i] = (int *) malloc( b * sizeof(int));
for(i = 0 ; i < a ; i++)
for(j = 0 ; j < b ; j++)
subset[i][j] = 0;
}
int main()
{
int **subset;
int a = 4, b = 4;
allocate2DArray(subset, a, b);
int i,j;
for( i = 0 ; i < a ; i++)
{
for( j = 0 ; j < b ; j++)
{
printf("%d ", subset[i][j]);
}
printf("\n");
}
}
When I comment the lines to print the array, it doens't give any error and program executes without segmentation fault. Please help me understand where I am going wrong.
All problems in computer science can be solved by another level of indirection:
void allocate2DArray(int ***p, int a, int b)
{
int **subset;
*p = (int **) malloc(a * sizeof(int *));
subset = *p;
// ...
allocate2DArray(&subset, a, b);
you must pass a int ***subset to the allocation function. This because arguments are passed by value.
You need this:
void allocate2DArray(int ***subset, int a, int b)
and this:
allocate2DArray(&subset, a, b);
By using int **subset; it does not become 2D array. It is still 1D storage and just pointer to pointer.
2D array means each element of a pointer buffer must point to a buffer which is suggested by ctn.
He has suggested ***ptr and *ptr is malloced which created 1st dimension of buffer.
Now when you call allocate2DArray() again subset is allocated memory which create second dimension. Which validate my above statement - each element of pointer buffer must point to a buffer.
so now with suggested code -
*p = (int **) malloc(a * sizeof(int *));
created an array each element of which point to buffer 'subset' which altogether create a true 2D array.
Related
I don't really understand why method 1 works but not method 2. I don't really see why it works for characters and not an int.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
/// WORK (METHODE 1)
char **string_array = malloc(sizeof(char **) * 10);
string_array[0] = "Hi there";
printf("%s\n", string_array[0]); /// -> Hi there
/// DOES NOT WORK (METHODE 2)
int **int_matrix = malloc(sizeof(int **) * 10);
int_matrix[0][0] = 1; // -> Segmentation fault
/// WORK (METHODE 3)
int **int_matrix2 = malloc(sizeof(int *));
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
int_matrix2[0][0] = 42;
printf("%d\n", int_matrix2[0][0]); // -> 42
}
In terms of the types, you want to allocate memory for the type "one level up" from the pointer you're assigning it to. For example, an int pointer (an int*), points to one or more ints. That means, when you allocate space for it, you should allocate based on the int type:
#define NUM_INTS 10
...
int* intPtr = malloc(NUM_INTS * sizeof(int));
// ^^ // we want ints, so allocate for sizeof(int)
In one of your cases, you have a double int pointer (an int**). This must point to one or more int pointers (int*), so that's the type you need to allocate space for:
#define NUM_INT_PTRS 5
...
int** myDblIntPtr = malloc(NUM_INT_PTRS * sizeof(int*));
// ^^ "one level up" from int** is int*
However, there's an even better way to do this. You can specify the size of your object it points to rather than a type:
int* intPtr = malloc(NUM_INTS * sizeof(*intPtr));
Here, intPtr is an int* type, and the object it points to is an int, and that's exactly what *intPtr gives us. This has the added benefit of less maintenance. Pretend some time down the line, int* intPtr changes to int** intPtr. For the first way of doing things, you'd have to change code in two places:
int** intPtr = malloc(NUM_INTS * sizeof(int*));
// ^^ here ^^ and here
However, with the 2nd way, you only need to change the declaration:
int** intPtr = malloc(NUM_INTS * sizeof(*intPtr));
// ^^ still changed here ^^ nothing to change here
With the change of declaration from int* to int**, *intPtr also changed "automatically", from int to int*. This means that the paradigm:
T* myPtr = malloc(NUM_ITEMS * sizeof(*myPtr));
is preferred, since *myPtr will always refer to the correct object we need to size for the correct amount of memory, no matter what type T is.
Others have already answered most of the question, but I thought I would add some illustrations...
When you want an array-like object, i.e., a sequence of consecutive elements of a given type T, you use a pointer to T, T *, but you want to point to objects of type T, and that is what you must allocate memory for.
If you want to allocate 10 T objects, you should use malloc(10 * sizeof(T)). If you have a pointer to assign the array to, you can get the size from that
T * ptr = malloc(10 * sizeof *ptr);
Here *ptr has type T and so sizeof *ptr is the same as sizeof(T), but this syntax is safer for reasons explained in other answers.
When you use
T * ptr = malloc(10 * sizeof(T *));
you do not get memory for 10 T objects, but for 10 T * objects. If sizeof(T*) >= sizeof(T) you are fine, except that you are wasting some memory, but if sizeof(T*) < sizeof(T) you have less memory than you need.
Whether you run into this problem or not depends on your objects and the system you are on. On my system, all pointers have the same size, 8 bytes, so it doesn't really matter if I allocate
char **string_array = malloc(sizeof(char **) * 10);
or
char **string_array = malloc(sizeof(char *) * 10);
or if I allocate
int **int_matrix = malloc(sizeof(int **) * 10);
or
int **int_matrix = malloc(sizeof(int *) * 10);
but it could be on other architectures.
For your third solution, you have a different problem. When you allocate
int **int_matrix2 = malloc(sizeof(int *));
you allocate space for a single int pointer, but you immediately treat that memory as if you had 10
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
You can safely assign to the first element, int_matrix2[0] (but there is a problem with how you do it that I get to); the following 9 addresses you write to are not yours to modify.
The next issue is that once you have allocated the first dimension of your matrix, you have an array of pointers. Those pointers are not initialised, and presumably pointing at random places in memory.
That isn't a problem yet; it doesn't do any harm that these pointers are pointing into the void. You can just point them to somewhere else. This is what you do with your char ** array. You point the first pointer in the array to a string, and it is happy to point there instead.
Once you have pointed the arrays somewhere safe, you can access the memory there. But you cannot safely dereference the pointers when they are not initialised. That is what you try to do with your integer array. At int_matrix[0] you have an uninitialised pointer. The type-system doesn't warn you about that, it can't, so you can easily compile code that modifies int_matrix[0][0], but if int_matrix[0] is pointing into the void, int_matrix[0][0] is not an address you can safely read or write. What happens if you try is undefined, but undefined is generally was way of saying that something bad will happen.
You can get what you want in several ways. The closest to what it looks like you are trying is to implement matrices as arrays of pointers to arrays of values.
There, you just have to remember to allocate the arrays for each row in your matrix as well.
#include <stdio.h>
#include <stdlib.h>
int **new_matrix(int n, int m)
{
int **matrix = malloc(n * sizeof *matrix);
for (int i = 0; i < n; i++)
{
matrix[i] = malloc(m * sizeof *matrix[i]);
}
return matrix;
}
void init_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int **matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
Here, each row can lie somewhere random in memory, but you can also put the row in contiguous memory, so you allocate all the memory in a single malloc and compute indices to get at the two-dimensional matrix structure.
Row i will start at offset i*m into this flat array, and index matrix[i,j] is at index matrix[i * m + j].
#include <stdio.h>
#include <stdlib.h>
int *new_matrix(int n, int m)
{
int *matrix = malloc(n * m * sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[m * i + j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[m * i + j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int *matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
With the exact same memory layout, you can also use multidimensional arrays. If you declare a matrix as int matrix[n][m] you will get what amounts to an array of length n where the objects in the arrays are integer arrays of length m, exactly as on the figure above.
If you just write that expression, you are putting the matrix on the stack (it has auto scope), but you can allocate such matrices as well if you use a pointer to int [m] arrays.
#include <stdio.h>
#include <stdlib.h>
void *new_matrix(int n, int m)
{
int(*matrix)[n][m] = malloc(sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int(*matrix)[m] = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
int(*matrix2)[m] = new_matrix(2 * n, 3 * m);
init_matrix(2 * n, 3 * m, matrix2);
print_matrix(2 * n, 3 * m, matrix2);
return 0;
}
The new_matrix() function returns a void * because the return type cannot depend on the runtime arguments n and m, so I cannot return the right type.
Don't let the function types fool you, here. The functions that take a matrix[n][m] argument do not check if the matrix has the right dimensions. You can get a little type checking with pointers to arrays, but pointer decay will generally limit the checking. The last solution is really only different syntax for the previous one, and the arguments n and m determines how the (flat) memory that matrix points to is interpreted.
The method 1 works only becuse you assign the char * element of the array string_array with the reference of the string literal `"Hi there". String literal is simply a char array.
Try: string_array[0][0] = 'a'; and it will fail as well as you will dereference not initialized pointer.
Same happens in method 2.
Method 3. You allocate the memory for one int value and store the reference to it in the [0] element of the array. As the pointer references the valid object you can derefence it (int_matrix2[0][0] = 42;)
I am a novice C programmer trying to write a function that dynamically allocates space for a 2D array. I am getting a segmentation fault when running this code & i'm not sure why.
#include <stdio.h>
#include <stdlib.h>
int allocate_space_2D_array(int **arr, int r, int c) {
int i,j;
arr = malloc(sizeof(int *) * r);
for (i = 0; i < r; i++)
arr[i] = malloc(sizeof(int *) * c);
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%p", arr[r][c]);
}
printf("\n");
}
return arr;
}
I expected to be able to print out and see the contiguous memory locations of each spot in the array, but I am never reaching that point in my code, because when I run it, i get a segmentation fault. Would appreciate any help.
Seeing your program i see 3 errors one while you allocate memory for 2D-array,one while you're printing and another one is how you declare the function.
First malloc is ok,the second one is wrong cause you already allocated memory for r(size of row) pointers so it's just like if you have * arr[r],so to allocate memory correctly now you should allocate memory just for int and not for int*.
Second error while printing you put as index for row and column the values r and c,but r and c are the size of matrix , as we know the size of an array or 2D-array goes from 0 to size-1,in your case goes from 0 to r-1 and from 0 to c-1.
Third error you should declare the function not as int but as int** cause you want to return a matrix so the return type is not int but int**.
I change your code to make it work correctly,it should be work.
int** allocate_space_2D_array(int **arr, int r, int c) {
int i,j;
arr = malloc(sizeof(int *) * r);
for (i = 0; i < r; i++)
arr[i] = malloc(sizeof(int ) * c);
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%p", arr[i][j]);
}
printf("\n");
}
return arr;
}
I am trying to make two dimensional array function, but somehow it is not working. The code here:
#include <stdio.h>
#include <stdlib.h>
int **multiTable (unsigned int xs, unsigned in ys)
{
unsigned int i, j;
int **table = int(**)malloc(xs * ys * sizeof(int*));
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
free(**table);
return table;
}
So first of all, should I also add inside the malloc the row (xs)? Or should it work, if I work only with the columns? --> like this:
int **table = int(**)malloc(ys * sizeof(int*));
That is not going to work as an array of pointers int **table is not contiguous and it is not equivalent to a 2d array table[a][b].
You can however use a pointer to an array if you want to use a single malloc.
int (*table)[xs] = malloc( ys * sizeof(*table));
for( int i = 0; i < ys; i++)
{
for( int j = 0; j < xs; j++)
{
table[i][j] = i;
}
}
free( table ) ;
And do not return table after you free it as your return call does.
It seems you mean the following
int ** multiTable( unsigned int xs, unsigned int ys )
{
unsigned int i, j;
int **table = malloc( ys * sizeof( int * ) );
for ( i = 0; i < ys; i++ )
{
table[i] = malloc( xs * sizeof( int ) );
for ( j = 0; j < xs; j++ )
{
table[i][j] = j * i;
}
}
return table;
}
'table' is a 2-D pointer. First understand what is a 2D pointer. A pointer is a special type of variable that is used to store the address of another variable. So a 2D pointer is a special variable that is again used to store the address of a pointer variable.
Now imagine that you have a single array of pointers(collection of base address of different 1-D array), that will store the base address of many 1-D arrays.
To dynamically allocate memory to this array of pointers you need the statement
table=(int**)malloc(sizeof(int*)*xs);
Now you have an array with 'xs' number of elements, and you can access each element by table[0], table[1], table[2]..and so on..., but none of these arrays is allocated memory. So you need to allocate memory to each of the array individually using a loop like this:
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
So your over-all program becomes:
int **table; // table is a 2D pointer
table=(int**)malloc(sizeof(int*)*xs);
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
return table;
You don't need to free the array before returning it. Doing so will make your pointer 'table' a dangling pointer that is still referring to a memory that is no longer allocated, so just return 'table' without the statement:
free(table);
The above statement will lead to a dangling memory that has no access point, ans so is useless. This is a memory leakage problem that arises when memory gets accumulated, and this memory is no more accessible through your program and could not be relocated for other purpose, such a memory is called dangling memory.
I am trying to dynamically allocate a 2D array, put some values, and print output. However it seems that I am making mistake in getting input to program in atoi() function.
Basically when we assign a static 2D array, we declare it as say int a [3][3]. So 3*3 units if int, that much memory gets allocated. Is same thing holds for allocating dynamic array as well?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(int arg,char* argv)
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
int (*arr)[col] = malloc(sizeof (*arr)*rows);
int *ptr = &(arr[0][0]);
int ct=1;
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
arr[i][j]=ct;
ct++;
}
}
printf("printing array \n");
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
free(arr);
return (0);
}
Program crashes in runtime. Can someone comment?
Try to change the third line to:
int main(int arg,char **argv)
The common method to use dynamic matrices is to use a pointer to pointer to something, and then allocate both "dimensions" dynamically:
int **arr = malloc(sizeof(*arr) * rows);
for (int i = 0; i < rows; ++i)
arr[i] = malloc(sizeof(**arr) * col);
Remember that to free the matrix, you have to free all "rows" in a loop first.
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
You are defining rows and col twice.... that would never work!
With traditional C, you can only have the array[][] structure for multiple dimension arrays work with compile time constant values. Otherwise, the pointer arithmetic is not correct.
For dynamically sized multi dimensional arrays (those where rows and cols are determined at runtime), you need to do additional pointer arithmetic of this type:
int *a;
int rows=3;
int cols=4;
a = malloc(rows * cols * sizeof(int));
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
a[i*rows + j] = 1;
free(a);
Alternatively, you can use double indirection and have an array of pointers each pointing to a one dimensional array.
If you are using GCC or any C99 compiler, dynamic calculation of multiple dimension arrays is simplified by using variable length arrays:
// This is your code -- simplified
#include <stdio.h>
int main(int argc, const char * argv[])
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
// you can have a rough test of sanity by comparing rows * col * sizeof(int) < SIZE_MAX
int arr[rows][col]; // note the dynamic sizing of arr here
int ct=1;
for (int i=0;i<rows;i++)
for(int j=0;j<col;j++)
arr[i][j]=ct++;
printf("printing array \n");
for (int i=0;i<rows;i++)
{
for(int j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
return 0;
} // arr automatically freed off the stack
With a variable length array ("VLA"), dynamic multiple dimension arrays in C become far easier.
Compare:
void f1(int m, int n)
{
// dynamically declare an array of floats n by m size and fill with 1.0
float *a;
a = malloc(m * n * sizeof(float));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i*n + j] = 1.0;
free(a);
}
With VLA you can write to do the same:
void f2(int m, int n)
{
// Use VLA to dynamically declare an array of floats n by m size and fill with 1.0
float a[m][n];
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i][j] = 1.0;
}
Be aware that unlike malloc / free VLA's handling of requesting a size larger than what is available on the stack is not as easily detected as using malloc and testing for a NULL pointer. VLA's are essentially automatic variables and have similar ease and restrictions.
VLA's are better used for smaller data structures that would be on the stack anyway. Use the more robust malloc / free with appropriate detection of failure for larger data structures.
If you are not using a fairly recent vintage C compiler that supports C99 -- time to get one.
Consider following codes:
#include <stdio.h>
#include <malloc.h>
void allocateMatrix(int **m, int l, int c)
{
int i;
m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
m[i] = (int*) malloc( sizeof(int) * c );
}
int main()
{
int **m;
int l = 10, c = 10;
allocateMatrix(m, l, c);
m[0][0] = 9;
printf("%d", m[0][0]);
return 0;
}
The code above will generate an memory allocation error and will crash.
But the code below will work correctly, the question is: WHY?
#include <stdio.h>
#include <malloc.h>
int** allocateMatrix(int l, int c)
{
int i;
int **m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
m[i] = (int*) malloc( sizeof(int) * c );
return m;
}
int main()
{
int **m;
int l = 10, c = 10;
m = allocateMatrix(l, c);
m[0][0] = 9;
printf("%d", m[0][0]);
return 0;
}
I cannot see why the first code crashes, since I'm just passing the pointer-to-pointer m (the variable that holds the memory first memory address of the matrix) as an argument. I see no difference between the codes (in practice). I would appreciate any clear explanation.
Thank you,
Rafael Andreatta
In the first example you don't initialize m. You merely change your copy of it. So, put otherwise, the caller will never see what you did to m.
In the second example you allocate memory and then return a pointer to it. Which is valid.
You might be able to fix your first example like this (untested but should work):
void allocateMatrix(int ***m, int l, int c)
{
int i;
*m = malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
(*m)[i] = malloc( sizeof(int) * c );
}
/* ... */
allocateMatrix(&m, l, c);
EDIT
Took me a while but I found it. As usual the C FAQ has something to say about this.
The function allocateMatrix receives a copy of the passed variable m, not the variable the you are passing from the main. Thus, in the first example m is not initialized and when you try to access is you get a segmentation fault.
This is a tricky one, and happens because with:
void allocateMatrix(int **m, int l, int c);
you're one level of indirection out. If you pass a pointer, the value that points to is in effect passed by reference. However, the actual pointer value is copied onto the stack, i.e. is still pass by value. So your allocation function has a local copy of the heap address, but this is never re-assigned to m in the preceding scope.
To fix this, you can use either the second case, or this:
void allocateMatrix(int ***m, int l, int c)
{
int i;
*m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
(*m)[i] = (int*) malloc( sizeof(int) * c );
}
and pass with &m.
I also would like to point out in C, you probably are better off not casting the result of malloc, although you are required to in C++. See this answer.
Because in first example variable m (in main) is not changed. To change it, you must pass it as reference (in C++) or by pointer (in plain C).