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;
}
Related
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've got a small part of simple code that keeps giving me segmentation fault each time I go through the realloc for loop in the second if statement.
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
x[i] = (int*) realloc(x[i],nNew*sizeof(int)); // seg fault
I think that the memory allocation has been done correctly (apparently not) but I cannot find the error.In the first if statement (where I de-allocate memory) it works correctly.
Sorry for the bad format.
void update(int **x,int n,int nNew)
{
int temp;
if(n>nNew)
{
*x = (int **) realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
*(x+i) =(int *) realloc(x[i],nNew*sizeof(int));
printf("temp %d",x[nNew-1][nNew-1]);
}
else if(n<nNew)
{
temp = x[n-1][n-1];
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
x[i] = (int*) realloc(x[i],nNew*sizeof(int)); // seg fault
printf("temp %d",**temp);
for(int i=n;i<(nNew);i++)
{
for(int j=n;j<(nNew);j++)
x[i][j] = temp;
}
}
}
int main()
{
int nNew = 9;
int n = 8;
int **x = (int **) malloc(n*sizeof(int*));
for (int i=0; i<n; i++)
x[i] = (int *)malloc(n * sizeof(int));
int count=0 ;
for(int i=0;i<n;i++)
{
count ++;
for(int j=0;j<n;j++)
x[i][j] = count;
}
update(x,n,nNew);
for(int i=0;i<nNew;i++)
free(x[i]);
free(x);
return 0;
}
You're not reallocating what you think you are.
When you do this:
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i
Since x has type int **, *x has type int *. Also, *x is the same as x[0]. So you're not reallocating the array of pointers on the first line but the first array of int. You need to call realloc on the original pointer, and you need to pass the address of that pointer so that the change is visible in the calling program.
Then for the reallocation of the individual arrays, you need to call realloc on the original n to grow or shrink them, then either free the extra rows if growing or malloc the newly added rows. In the growing case you want to realloc the array of pointers fisrt, and in the shrinking case you want to do that last.
So after those changes your update function should look like this:
void update(int ***x, int n, int nNew)
{
if(n>nNew) {
// shrink each row to be kept
for(int i=0;i<nNew;i++)
(*x)[i] = realloc((*x)[i],nNew*sizeof(int));
// free the extra rows
for(int i=nNew;i<n;i++)
free((*x)[i]);
// shrink the list of rows
*x = realloc(*x,nNew*sizeof(int*));
} else if(n<nNew) {
// grow the list of rows
*x = realloc(*x,nNew*sizeof(int*));
// grow the existing rows
for(int i=0;i<n;i++)
(*x)[i] = realloc((*x)[i],nNew*sizeof(int));
// create the new rows
for(int i=n;i<nNew;i++)
(*x)[i] = malloc(nNew*sizeof(int));
}
}
And you call it like this:
update(&x,n,nNew);
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 4 years ago.
So what I'm trying to do is create a two dimensional array as a matrix using pointers. I put a double pointer into my CreateMatrix function, along with rows/cols, and I dynamically allocate the arrays into them. I filled 10 into all of them to test, and it shows they're all allocated. However in main, when I try to access an arbitrary value of the 2D array, I segfault. Regardless of if it occurs in a function, shouldn't dynamically allocated be stored onto the heap, thus it should work?
void CreateMatrix(int ** matrix, int row, int col){
int i, j;
matrix = (int**)malloc(row* sizeof(int*));
for (i = 0; i < row; i++) {
matrix[i] = (int*)malloc(col* sizeof(int));
for (j = 0 ; j < col; j++) {
matrix[i][j] = 10;
printf("i: %d, j: %d\n", i,j);
printf("%d",matrix[i][j]);
}
}
}
In main:
int ** matrix1;
int m1row, m1col = 5;
CreateMatrix(matrix1, m1row, m1col);
fprintf(stdout,"Testing if got out");
fflush(stdout);
printf("This should be 10 : %d",matrix1[0][0]); //definitely segfaults here
Also, a side question; I was told that when passing 'by reference' in C, not only do you need pointers in the function definition, but an ampersand on the variable for the function call. Something like if I want to pass the matrix a by reference : CreateMatrix(&a, b, c); instead of CreateMatrix(a, b, c);. If I use an &, I get an incompatibility error saying the argument is a triple pointer,when I need a double pointer. (Which in theory makes sense, since you're passing the location of the double pointer). Then is & only used for non pointer variables?
matrix in CreateMatrix is a copy of the pointer matrix1. When you assign to matrix in that function, matrix1 in main is unaffected.
int** CreateMatrix(int row, int col){
int i, j;
int **matrix = (int**)malloc(row* sizeof(int*));
for (i = 0; i < row; i++) {
matrix[i] = (int*)malloc(col* sizeof(int));
for (j = 0 ; j < col; j++) {
matrix[i][j] = 10;
printf("i: %d, j: %d\n", i,j);
printf("%d",matrix[i][j]);
}
}
return matrix;
}
int main() {
// ...
int **matrix1 = CreateMatrix(row, col);
// ...
return 0;
}
If you want to keep a void return type, then take a pointer to a int** pointer and pass address of that pointer in main.
void CreateMatrix(int ***matrix, int row, int col){
int i, j;
*matrix = (int**)malloc(row* sizeof(int*));
for (i = 0; i < row; i++) {
(*matrix)[i] = (int*)malloc(col* sizeof(int));
for (j = 0 ; j < col; j++) {
(*matrix)[i][j] = 10;
printf("i: %d, j: %d\n", i,j);
printf("%d", (*matrix)[i][j]);
}
}
}
int main() {
int **matrix1;
CreateMatrix(&matrix1, 10, 10);
printf("This should be 10 : %d",matrix1[0][0]);
return 0;
}
Variables reside in memory. A pointer store the memory address of a variable with a specific type. The ampersand & gives the memory address of a variable.
Here, & returns the address to the int** pointer, matrix1, which is then passed to CreateMatrix. Notice that the argument matrix of CreateMatrix has been changed to be a pointer to a int** pointer.
Dereferencing a pointer gets you the object that the pointer is pointing to. Here, when we assign to *matrix, what we are doing is essentially using the memory address of matrix1 (which was passed via matrix) to get matrix1 in CreateMatrix, and assign the start of the block of memory allocated by malloc to matrix1.
In your original code, matrix in CreateMatrix is a copy of the value of the pointer matrix1 (probably garbage because it is not initialized).
When you assign to matrix, you are not modifying matrix1, you are merely modifying a local variable.
There are few issues with the code you mention. firstly m1row value is not defined, so it may consider some garbage value, so assign the value like
int m1row = 5, m1col = 5;
Secondly, you are passing matrix1 to CreateMatrix() function & creating dynamic array in the CreateMatrix() function but not returning the dynamically allocated address to main() function which causes segmentation fault when accessing
printf("This should be 10 : %d",matrix1[0][0]);
Also casting the malloc() result is not required as pointed here.
Sample Code
int** CreateMatrix(int row, int col){
int i, j;
int **matrix = malloc(row* sizeof(*matrix)); /* no need to cast the malloc result */
for (i = 0; i < row; i++) {
matrix[i] = malloc(col* sizeof(**matrix));
for (j = 0 ; j < col; j++) {
matrix[i][j] = 10;
#if 0
printf("i: %d, j: %d\n", i,j);
printf("%d \n",matrix[i][j]);
#endif
}
}
return matrix; /* return the dynamic array */
}
int main(void){
int m1row = 5, m1col = 5;
int **matrix1 = CreateMatrix(m1row, m1col);
printf("\nThis should be 10 : %d\n",matrix1[0][0]);
return 0;
}
The matrix argument of the CreateMatrix function is allocated on the stack of that function, which means that it is local to it. When you use malloc to allocate memory, the local variable matrix is pointing to that memory. The matrix variable in main does not get updated by that, this is because arguments are by default passed by value.
In order to make it work, you would have to pass the address of the matrix variable (using the & operator) from main to CreateMatrix, i.e. its signature should have int *** matrix. Inside the function you would have to update it by using the * operator. Like so:
*matrix = (int **) malloc (row * sizeof(int *))
Another option is instead to return the allocated memory from the CreateMatrix function.
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 have a function which creates a 2D array:
float** createMatrix(int x, int y){
float** array= malloc(sizeof(float*) * y);
for(int i=0; i<y; i++)
array[i] = malloc(sizeof(float) * x);
return array;
}
Now I can create a 2D array:
float** temp=createMatrix(2,2);
I also have a function, for e.g., which transposes my "matrix" (2D array):
float** matrixTranspose(float** m, int x, int y){
float** result=createMatrix(y, x);
for(int i=0; i<y; i++){
for(int j=0;j<x; j++) result[j][i]=m[i][j];
}
return result;
}
Now if I do this:
temp=matrixTranspose(temp,2,2);
what happens with the old memory previously allocated to temp? My transpose function allocates new memory chunk. Obviously I would have to somehow free "old temp" after the Transposition, but how (elegantly)?
Your free can mirror your allocation:
int i;
for(i = 0; i < y; i++)
free(array[i]);
free(array);
But if you assign to temp the new matrix created by matrixTranspose, then you'll lose your pointer to that memory. So keep track of that with another pointer, or assign the result of matrixTranspose to another pointer:
float **transposedMatrix = matricTranspose(...);
If you consider your matrices as mutable, you could also transpose them in place: rather than allocating a new matrix in the matrixTranspose function, you move around the numbers in the existing array. You can do this in place with one float temp.
Use another variable (pointer), when calling matrixTranspose. Then, write a function for free-ing memory of a matrix.
Like this:
float** newTemp = matrixTranspose(temp,2,2);
freeMatrix( temp );
temp = newTemp;
Otherwise, you'll loose the memory, pointed by temp and thus you have a memory leak.
freeMatrix should be symmetric to the allocating memory:
for(int i=0; i<y; i++)
free( array[i] );
free( array );
You don't do this. You're gonna need two variables for this.
float **tmp2 = matrixTranspose(temp, 2, 2);
and write a deallocator function for the matrix:
void freeMatrix(float **m, int x) {
int i;
for (i = 0; i < x; i++) {
free(m[i]);
}
free(m);
}
and only then you can assign
temp = tmp2;
int FreeMatrix(char **matrix, int x, int y) {
int i;
for(i=0; i<y; i++) {
free(matrix[i]);
}
free(matrix);
}
The not-so-elegant part, here, is that you have to keep track of the allocated ranges. There are various ways to handle this, most involve keeping track of them, e.g. by wrapping malloc and free. Google for 'malloc free multidimensional arrays'.