Memory leaking when allocating memory - c

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'.

Related

Can someone explain me what is going on in this statement?

Basically i understand pointers. But when it comes to dynamic allocation for matrices which also involve pointers, i'm getting lost in the process. I wanna know how can i translate this segment of code in order to understand it.
(*a)[i] = (int*)malloc((*m) * sizeof(int));
The function for reading the matrix looks like this:
void reading(int *n, int *m, int ***a) {
int i, j;
printf("n=");
scanf("%d", &*n);
printf("m=");
scanf("%d", &*m);
(*a) = (int**)malloc((*n) * sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
}
And also what is the meaning of ***a in the declaration. I was told at college that te first asterisk stands for dynamic allocation and the other two's from the fact that is a matrix involved. For vectors dynamic allocation is **v and so on... but i can't naturally explain it in my mind in order understand what is happening in it.
First let me answer your question about this specific line:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
What this is doing is allocating an array of exactly *m integers and saving a pointer to it into the array *a of pointers to int, which was previously allocated as:
(*a) = (int**)malloc((*n) * sizeof(int*));
Now, if it still isn't clear what is going on, re-writing the code in a more meaningful way will help. To make things easier, you can use temporary variables to work, and assign the values to the pointers passed as arguments only at the end of the function. Using more meaningful names also helps a lot.
void read_matrix(int *rows, int *columns, int ***matrix) {
int i, j, r, c;
int **mat;
printf("n = ");
scanf("%d", &r);
printf("m = ");
scanf("%d", &c);
// Allocate space for a matrix (i.e. an array of r integer pointers).
mat = malloc(r * sizeof(int*));
// Allocate space for each row of the matrix (i.e. r arrays of c integers).
for (i = 0; i < r; i++)
mat[i] = malloc(c * sizeof(int));
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}
*rows = r;
*columns = c;
*matrix = mat;
}
Since we now moved the assignment of the values to the arguments at the end of the function, we got rid of all the annoying pointer dereference operators (*), and the code looks way cleaner.
You can see that what previously was:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
now became:
mat[i] = malloc(c * sizeof(int));
Which is much easier to understand. This is allocating space for an array (a row of the matrix) holding c integers.
What previously was:
(*a) = (int**)malloc((*n) * sizeof(int*));
now became:
mat = malloc(r * sizeof(int*));
This is allocating an array of r integer pointers (which means a matrix of r rows, if each pointer points to a row).
You don't show how this function is called, but presumably it looks something like this:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
So in this context, matrix is defined as a pointer-to-pointer. It can hold the address of the first element of an array of int *, each of which can hold the address of the first element of an array of int.
When &matrix is then passed to this function, you have a pointer-to-pointer-to-pointer, which is what the argument a of reading is. In this context, a contains a pointer to a single int **, specifically matrix in the calling function. By dereferecing a in reading, you're actually accessing matrix in the calling function.
So now getting to this line:
(*a) = (int**)malloc((*n) * sizeof(int*));
This allocates space for an array of *n int * and assigns that to *a, (i.e. matrix in the calling funtion. So now you have an array of int *. Now for this:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
This loops through the elements of the int * array and assigns to each one a pointer to a memory block big enough for *m int.
So you now effectively have a 2D array of int. Note however that this is not the same as an actual 2D array of int which would be declared as int arr[n][m].
First, you are doing too many different things in a single function, which is making it a bit messy. I suggest that you separate out the logic to get the matrix size from the logic to create the matrix:
void get_size(int *n, int *m) {
printf("n=");
scanf("%d", n);
printf("m=");
scanf("%d", m);
}
int **create_matrix(int n, int m) {
int **matrix = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
matrix[i] = malloc(m * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", [i][j]);
}
}
}
From here it is a lot easier to see what is going on, with fewer *s and &s.
Your matrix is implemented as an array of arrays, so
int **matrix = malloc(n * sizeof(int*));
allocates memory for the outer array, while
matrix[i] = malloc(m * sizeof(int));
allocates memory for each of the inner arrays.
int ***a declares a to be a pointer to a pointer to pointer to an int. The caller is required to have their own int ** and to pass its address to this function. For example, the caller might define int **x; and pass &x to this function for the parameter a. I will use x to refer to the caller’s int **.
(*a) = (int**)malloc((*n) * sizeof(int*)); sets the caller‘s pointer (x) to point to space for *n pointers to int. This is preparation for fabricating a matrix of *n rows—memory will be allocated for each row, and we will have a pointer to that memory, so we need n pointers.
Then these lines:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
allocate memory for *n rows. The second line allocates memory for an array of m int and sets x[i] to point to the first element of that memory. Note that since a is an int ***, *a is an int **, and (*a)[i] is an int *. Thus, *a points to an array of int * elements.
Finally, these lines:
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
set each element of the *n by *m array: For each element x[i][j] (referred to as (*a)[i][j], it passes the address of the element (&(*a)[i][j]) to scanf to be set from the input stream.

segmentation fault double pointer realloc

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);

Seg faulting when accessing dynamically allocated memory in main (allocated in function), C [duplicate]

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.

Allocating contiguous memory for a 3D array in 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.

Dynamically allocated array - elements not accessible

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;
}

Resources