user3075598
user3075598

Reputation: 13

double pointer and memory allocation

I have a structure that uses double pointers to make a matrix:

typedef struct
{
       int rows, cols;
       int** element;
}Matrix;

I am writing a function that initializes a matrix by dynamically allocating memory to this structures. This is the code I have written but I get a segmentation fault when I try to access a->rows,cols, or element in another function or in main.

void matrixInit (Matrix* ma, int m, int n)
 {   int i;
     ma=(Matrix*)malloc(sizeof(Matrix));
     ma->rows=m;
     ma->cols=n;

     ma->element=malloc(m*sizeof(int*));
     for(i=0;i<m;i++)
        {ma->element[i]=malloc(n*sizeof(int));
        }

 }

Any help please?

Upvotes: 1

Views: 2126

Answers (4)

pepo
pepo

Reputation: 699

When you call a function like this, you pass it a value of a pointer to a matrix. When you actually create the matrix in the function, you only assign it locally.

You should pass a pointer to the variable where the matrix pointer is to be stored, i.e. Matrix **ma.

void matrixInit (Matrix **ma_ptr, int m, int n)
{
    int i;
    *ma_ptr = (Matrix*)malloc(sizeof(Matrix));

    Matrix *ma = *ma_ptr;
    ma->rows=m;
    ma->cols=n;
    ma->element=malloc(m*sizeof(int*));
    for(i=0;i<m;i++)
    {
        ma->element[i]=malloc(n*sizeof(int));
    }
}

and then call this method with an address ofthe variable where you want your matrix to be stored.

Matrix *m;
matrixInit(&m, 4, 4);

Another way is to allocate memory for the matrix itself outside of the function. Your function will stay exactly the way you wrote it, except you remove the allocation

ma = (Matrix*)malloc(sizeof(Matrix));

Then you will pass it a pointer to a Matrix, but you have to ensure it points to a Matrix struct. You can do this by declaring a Matrix* variable and calling malloc() outside of the function (and thus allocating it on the heap), or declare a variable of type Matrix (and have it allocated on the stack).

Matrix ma;
matrixInit(&ma, 4, 4);

Upvotes: 0

Roddy
Roddy

Reputation: 68033

Your function doesn't return the matrix it creates. Do this instead.

Matrix * matrixInit (int m, int n)
 {
   Matrix* ma;
   int i;
     ma=(Matrix*)malloc(sizeof(Matrix));
     ...
     return ma;
 }

... and then use it thus

Matrix * myMatrix;
myMatrix = matrixInit(8,8);  // chessboard

Upvotes: 0

kviiri
kviiri

Reputation: 3302

In C, every function argument is passed by value. This means that when you give an argument to a function, a copy of the value (not the value itself) is passed as the argument in the function. This includes pointers - you can change whatever the pointer refers to and have no problems, but if you set the pointer to point to something else in the function, the change only applies to a local copy of the pointer.

ma=(Matrix*)malloc(sizeof(Matrix));

Here, instead of making the input pointer point to a newly allocated memory for a Matrix struct, you are in fact overwriting a local pointer ma with a new one without doing anything to the input pointer. This causes the issue. To fix this, you could return a pointer to ma instead.

Upvotes: 1

Kninnug
Kninnug

Reputation: 8053

You'll want to pass in a pointer-to-pointer-to-Matrix so that the malloced pointer is available to the caller. Like this:

void matrixInit (Matrix ** ma, int m, int n)
{
    *ma = malloc(sizeof **ma); // sizeof **ma == sizeof(Matrix)

Then call it with this:

Matrix * matx;
matrixInit(&matx, 3, 4);

Upvotes: 0

Related Questions