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;
}
Related
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.
How to find number of rows in dynamic 2D char array in C?
Nothing from there.
tried with following code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int k = 97;
void foo(char **a)
{
int i = 0;
for(i=0; a[i] != NULL; ++i)
printf("i = %d\n", i);
}
void strcpyo(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++){
a[i]=b[i];
}
a[i]='\0';
}
void strcpym(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++);
memcpy(a,b,i+1);
}
void freee(char** ptr){
int i;
for(i = 0;i < k; ++i)
{
free(ptr[i] );
}
free(ptr);
}
void alloc(char ***p)
{
*p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
// for(i = 0;i < j; ++i)
{
(*p)[j] = (char *)malloc(11 * sizeof(char));
strcpy((*p)[j],"paicharan");
}
//printf("j = %d ", j);
//foo(p);
}
}
int main()
{
char **p;
alloc(&p);
#if 0
char **p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
for(i = 0;i < j; ++i)
{
p[i] = (char *)malloc(11 * sizeof(char));
strcpy(p[i],"paicharan");
}
printf("j = %d ", j);
foo(p);
}
#endif
foo(p);
freee(p);
return 0;
}
The code in #if 0 #endif works perfectly, but if I do create arrays in function alloc(char**) it's giving the wrong answer for odd number of rows in array. Can anybody explain why?
ie. for k= odd number it gives out wrong answer but for even number its correct.
Your code depends on Undefined Behaviour to work correctly i.e. it'll work only by chance. This has got nothing to do with even or odd count of elements.
In the void alloc(char ***p) function you allocate memory for k pointer to pointer to char: char**. Then you fill all of the k pointers with new valid char* pointers i.e. none of them are NULL. Later in void foo(char **a) you do for(i=0; a[i] != NULL; ++i); since a[k - 1] was non-null, it'll iterate over them correctly. BUT after that a[k] may or may not be NULL, you never know what is in there. Also accessing what is beyond the array you allocated is undefined behaviour (due to out of bounds access).
Making k + 1 elements and setting the kth element to NULL makes this work; make sure you free all of k + 1 elements and not leak the last sentinal element.
Since you told that the code wraped inside the macro works fine, I've ignored that; don't know if there's UB there too. If you're doing this exercise to learn, it's fine. If you are planning to do some other project, try to reuse some existing C library which already gives these facilities.
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.
I was writing a matrix multiplication program, and to save code space I created a function make that takes a pointer to a double pointer and dynamically allocates a 2-dimensional array of given size. The arrays a and b are intialised to random values in [-2, 2]. However, when I try to run the code on gcc, I get a seg fault.
I ran the code through gdb, and the error arises when I try to set b[0][0] to a random number. When I try to print b[0][0] in gdb, I get the error:
Cannot access memory at address 0xbfebfdc3f5d77f80
However, I'm actually able to access b[0][0] before this. I can print the array just after allocating it without errors. For some reason, it's always the array b that seems to cause problems.
I've a feeling it's a pointer issue, but I can't see where. I'm not that inexperienced a programmer, but I spent the guts of 2 days trying to find out why this error keeps appearing. Can anyone shed some light?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void make(double ***a, int m, int n)
{
int i;
double *tmp;
(*a) = (double **) malloc(m*sizeof(double *));
tmp = (double *) calloc(m*n,sizeof(double));
if(tmp == NULL)
{
printf("Error with malloc.\n");
exit(EXIT_FAILURE);
}
for(i=0;i<m;i++)
(*a)[i] = &tmp[i*n];
free(tmp);
if(a == NULL)
{
fprintf(stderr, "Error with the matrix, dimensions: %d, %d. \n", m, n);
exit(EXIT_FAILURE);
}
}
int main()
{
int i, j;
int l, m, n;
double **a, **b, **c;
l = m = n = 8;
srand48(time(NULL));
make(&a, l, m);
make(&b, m, n);
make(&c, l, n);
for(i=0; i<l; i++)
for(j=0; j<m; j++)
a[i][j] = (drand48()*4.0) - 2.0;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
b[i][j] = (drand48()*4.0) - 2.0;
free(a);
free(b);
free(c);
return 0;
}
One problem is the call to free(tmp) in make. That is the memory that was allocated for the array. It should not be freed if you plan to continue using it.
You need to allocate memory for every row in the "would-be 2D array", you only allocate memory for the first row, then have every pointer point at that same data. This doesn't make any sense.
You don't check if the first malloc call succeeded.
You shouldn't call free from this function.
It is always best to create a true 2D array with adjacently allocated memory cells, rather than some pointer-to-pointer mess.
i have pasted my partial code over here
int *nn,*kk;
int main()
{
int t=0,i;
scanf("%d",&t);
int maxx=0;
nn = new int [t];
kk = new int [t];
for(i=0;i<t;i++)
{
scanf("%d%d",&n,&k);
nn[i] = n;
kk[i] = k;
if(maxx<n)
maxx=n;
cout<<nn[i]<<" "<<kk[i]<<endl;
}
t=0;
for(i=0;i<t;i++)
{
n = nn[i];
k = kk[i];cout<<nn[i]<<" "<<kk[i]<<endl;
//cout<<setprecision(6);
if(k<34&&n>k)
//cout<<a[n][k]<<endl;
printf("%0.7lf\n",a[n][k]);
else
printf("0.000000\n");//cout<<"0\n";
}
delete []nn;
delete []kk;
return 0;
}