# Thread: Problem of allocation memory

1. ## Problem of allocation memory

hey guys i have a little project i need to write a program that can calculate two matrix and put the sum in triple pointer,for first i need to allocate memory for triple pointer .
my problem is that when i try to free i got error
i will show you the relevant parts of the code/
the Error is :

Code:
```int mat_mul(float m1[ROWS][COLS], float m2[ROWS][COLS], float *** C){
int i, j;
float temp[6], temp1[6];
float res[ROWS][COLS];

allocate_mem(C);
for (i = 0; i < 6; i++) {
GetValue(&m1[ROWS][COLS], &m2[ROWS][COLS], temp, temp1, i);
multiply(&m1[ROWS][COLS], &m2[ROWS][COLS], C);
if (C!=NULL)
return 1;
else
return -1;
}
}```
Code:
```void multiply(float mat1[][COLS], float mat2[][COLS], float res[][COLS])    {
int i, j, k;
for (i = 0; i  <= COLS; i++)
{
for (j = 0; j <= COLS; j++)
{
res[i][j] = 0;
for (k = 0; k <= COLS; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
}
}

}```
Code:
```void deallocate_mem(float*** arr) {
for ( int i = 0; i < COLS; i++)
free((*arr)[i]);
free(*arr);
}```
Code:
```void allocate_mem(float*** arr){
*arr = (float**)malloc(COLS * sizeof(float*));
for (int i = 0; i < COLS; i++)
(*arr)[i] = (float*)malloc(ROWS * sizeof(float));```
Code:
```void GetValue(float m1[ROWS][COLS], float m2[ROWS][COLS],float* q1,float* q2,int i) {

m1[0][0] = m1[1][1] = cos(q1[i]);
m2[0][0] = m2[1][1] = cos(q2[i]);
m1[0][2] = m1[1][2] = m2[0][2] = m2[1][2] = 0;
m1[0][1] = sin(q1[i]);
m2[0][1] = sin(q2[i]);
m1[1][0] = -sin(q1[i]);
m2[1][0] = -sin(q2[i]);
m1[2][2] = 1;
m2[2][2] = 1;
m1[2][0] = 0.5*cos(q1[i]);
m2[2][0] = 0.5*cos(q2[i]);
m1[2][1] = 0.5*sin(q1[i]);
m2[2][1] = 0.5*sin(q2[i]);

}```

2. You seem to have a fundamental problem: you're dealing with matrices of ROWS number of rows and COLS number of columns. You cannot multiply two such matrices unless they are square matrices.

If you are really dealing only with square matrices such that ROWS and COLs are always going to be the same value, then stop messing around with with different constants as if you're allowing for matrices that are not square matrices. Just have a single constant, maybe call it DIM. If not, I suggest a redesign. Declare a struct like this:
Code:
```typedef struct {
float **entries;
int rows;
int cols;
} Matrix;```
Now, your memory allocation and deallocation functions will look like this (you'll need to add error checking):
Code:
```void allocate_mem(Matrix *matrix) {
float *data = malloc(matrix->rows * matrix->cols * sizeof(matrix->entries[0][0]));
matrix->entries = malloc(matrix->rows * sizeof(matrix->entries[0]));
for (int i = 0; i < matrix->rows; i++) {
matrix->entries[i] = data + i * matrix->cols;
}
}

void deallocate_mem(Matrix *matrix) {
free(matrix->entries[0]);
free(matrix->entries);
matrix->entries = NULL;
}```
Then for multiplication:
Code:
`int mat_mul(const Matrix *m1, const Matrix *m2, Matrix *result)`
at the start, you'll do a sanity check to see if m1 really can be multiplied by m2 based on m1->cols == m2->rows, and you'll set result->rows and result->cols accordingly before passing it to allocate_mem. Notice that the storage for the Matrix object itself (not the entries) is done even before you call mat_mul, allowing the caller the flexibility of having say, a Matrix object on the stack whose address gets passed to mat_mul, or perhaps a dynamically allocated one represented by a pointer.

On the other hand, you are only dealing with square matrices, then delete allocate_mem and deallocate_mem. They are a waste of time and effort. You already know that your result matrix is going to be a float[COLS][COLS] (or float[DIM][DIM], if you take my suggestion). No dynamic allocation needed.

3. Originally Posted by laserlight
You seem to have a fundamental problem: you're dealing with matrices of ROWS number of rows and COLS number of columns. You cannot multiply two such matrices unless they are square matrices.

If you are really dealing only with square matrices such that ROWS and COLs are always going to be the same value, then stop messing around with with different constants as if you're allowing for matrices that are not square matrices. Just have a single constant, maybe call it DIM. If not, I suggest a redesign. Declare a struct like this:
Code:
```typedef struct {
float **entries;
int rows;
int cols;
} Matrix;```
Now, your memory allocation and deallocation functions will look like this (you'll need to add error checking):
Code:
```void allocate_mem(Matrix *matrix) {
float *data = malloc(matrix->rows * matrix->cols * sizeof(matrix->entries[0][0]));
matrix->entries = malloc(matrix->rows * sizeof(matrix->entries[0]));
for (int i = 0; i < matrix->rows; i++) {
matrix->entries[i] = data + i * matrix->cols;
}
}

void deallocate_mem(Matrix *matrix) {
free(matrix->entries[0]);
free(matrix->entries);
matrix->entries = NULL;
}```
Then for multiplication:
Code:
`int mat_mul(const Matrix *m1, const Matrix *m2, Matrix *result)`
at the start, you'll do a sanity check to see if m1 really can be multiplied by m2 based on m1->cols == m2->rows, and you'll set result->rows and result->cols accordingly before passing it to allocate_mem. Notice that the storage for the Matrix object itself (not the entries) is done even before you call mat_mul, allowing the caller the flexibility of having say, a Matrix object on the stack whose address gets passed to mat_mul, or perhaps a dynamically allocated one represented by a pointer.

On the other hand, you are only dealing with square matrices, then delete allocate_mem and deallocate_mem. They are a waste of time and effort. You already know that your result matrix is going to be a float[COLS][COLS] (or float[DIM][DIM], if you take my suggestion). No dynamic allocation needed.

wow ,first of all thank you !!!
but in my project with must use the triple pointer

4. > GetValue(&m1[ROWS][COLS], &m2[ROWS][COLS], temp, temp1, i);
This isn't how you pass on your input parameters.

Code:
`GetValue(m1, m2, temp, temp1, i);`
> multiply(&m1[ROWS][COLS], &m2[ROWS][COLS], C);
...
> void multiply(float mat1[][COLS], float mat2[][COLS], float res[][COLS])
Your C is of type float ***, and that in no way is the same as float res[][COLS]

This might work.
Code:
`multiply(m1, m2, *C);  // turns your ***C into a ** to match what multiply expects`
Along with
Code:
```void multiply(float mat1[][COLS], float mat2[][COLS], float **res)    {
int i, j, k;
for (i = 0; i  <= COLS; i++)
{
for (j = 0; j <= COLS; j++)
{
res[i][j] = 0;
for (k = 0; k <= COLS; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
}
}

}```
All those <= COLS mean you're running off the ends of your arrays.

The idiomatic loop for subscripting arrays of dimension N is for ( i = 0 ; i < N ; i++ )

5. Originally Posted by cbeginner12334
but in my project with must use the triple pointer
So, this is a school project with artificial constraints? Then indeed you have to use a triple pointer, but you should also be aware that this might be because your instructor is a three star programmer (might be individually skilled, but is a pretty poor programmer when it comes to programming in teams or for the long haul because of an inability or refusal to use abstractions appropriately).

Yet, you haven't addressed the point I raised: are you dealing only with square matrices?

6. Originally Posted by laserlight
So, this is a school project with artificial constraints? Then indeed you have to use a triple pointer, but you should also be aware that this might be because your instructor is a three star programmer (might be individually skilled, but is a pretty poor programmer when it comes to programming in teams or for the long haul because of an inability or refusal to use abstractions appropriately).

Yet, you haven't addressed the point I raised: are you dealing only with square matrices?
and COLS==ROWS==2
yes all matrix square/

7. Originally Posted by cbeginner12334
and COLS==ROWS==2
yes all matrix square/
I'm still really puzzled as to why your instructor wants to use dynamic memory allocation instead of yet another 2D array, but let's chalk that up to you learning dynamic memory allocation for a possibly jagged 2D array.

As I mentioned, it would be best to replace ROWS and COLS with a single constant like DIM.

Salem mentioned a few points to take note in post #4. I'd say that the key here is to understand that you're trying to allocate memory for a float**, but you need a float*** only the memory allocation function because you're using the parameter as an out parameter. Recall that if you have an int in main and you want to change it from within a function such that it affects the int in the main function, you need to pass a pointer. For example:
Code:
```#include <stdio.h>

void foo1(int *x)
{
*x = 123;
}

void foo2(int x)
{
x = 456;
}

int main(void)
{
int x = 0;
foo1(&x);
printf("x=%d\n", x); // x has been changed to 123
foo2(x);
printf("x=%d\n", x); // x was not changed to 456
return 0;
}```
So, if you have a float** and want to change it (i.e., assign to it the address of the dyanamically allocated memory) in your memory allocation function, you need a float***. In all other places, as long as you are only dealing with the content of the matrix, you only need a float** parameter. This is true even of the memory deallocation function (unless you want to set the pointer to be a null pointer from within the memory deallocation function).

This should allow you to keep things simple while continuing to use the float*** as required where it is in fact needed.