2D Dynamic Array Allocation and Passing by Reference in C

Can someone wiser than I please explain to me why the following code segment faults? There is no problem allocating the memory by reference, but as soon as I try to assign anything or free by reference, segfault occurs.

I'm sure I'm missing some fundamental concept about pointers and passing by reference, hopefully some light can be shed.

#include <stdlib.h>
#include <stdio.h>

void allocateMatrix(float ***);
void fillMatrix(float ***);
void freeMatrix(float **);

int main() {
    float **matrix;

    allocateMatrix(&matrix);        // this function calls and returns OK
    fillMatrix(&matrix);            // this function will segfault
    freeMatrix(matrix);             // this function will segfault

    exit(0);
}

void allocateMatrix(float ***m) {
    int i;
    m = malloc(2*sizeof(float*));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }
    return;
}

void fillMatrix(float ***m) {
    int i,j;
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            (*m)[i][j] = 1.0;        // SEGFAULT
        }
    }
    return;
}

void freeMatrix(float **m) {
    int i; 
    for (i = 0; i < 2; i++) {
        free(m[i]);                  // SEGFAULT
    }
    free(m);
    return;
}

Answers


One set of problems is here:

void allocateMatrix(float ***m) {
    int i;
    m = malloc(2*sizeof(float*));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }
    return;
}

You need to assign to *m to get the information back to the calling code, and also you will need to allocate to (*m)[i] in the loop.

void allocateMatrix(float ***m)
{
    *m = malloc(2*sizeof(float*));
    for (int i = 0; i < 2; i++)
        (*m)[i] = malloc(2*sizeof(float));
}

There's at least a chance that the other functions are OK. The fillMatrix() is written and invoked correctly, though it could be simplified by losing the third * from the pointer:

void fillMatrix(float **m)
{
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
            m[i][j] = 1.0;        
    }
}

It might be advisable to pass the triple-pointer to freeMatrix() so that you can zero the pointer in the calling function:

void freeMatrix(float ***m)
{
    for (int i = 0; i < 2; i++)
        free((*m)[i]);
    free(*m);
    *m = 0;
}

Calling then becomes:

allocateMatrix(&matrix);
fillMatrix(matrix);
freeMatrix(&matrix);   

Good use of indirection. Just try to be consistent with format. It improves readability and reduces errors. e.g.

function calls:

    allocateMatrix  &matrix
    fillMatrix  &matrix
    freeMatrix  &matrix

declarations

void allocateMatrix  float ***m
void fillMatrix  float ***m
void freeMatrix  float ***m

handling

    (*m)[i] = malloc(2 * sizeof(float))
    (*m)[i][j] = 1.0
    free  (*m)[i]

Returning of pointer from your function is probably the better way to allocate memory:

float **allocateMatrix() {
    int i;
    float **m;

    m = malloc(2*sizeof(float *));
    for (i = 0; i < 2; i++) {
        m[i] = malloc(2*sizeof(float));
    }

    return m;
}

int main() {
    float **m;

    m = allocateMatrix();

    /* do other things 
       fillMatrix(matrix);
       freeMatrix(&matrix);
    */
}

Need Your Help

Facebook: get list of users that has granted permission to use the app

facebook facebook-graph-api facebook-javascript-sdk facebook-php-sdk

Is there a way to get a list of users that has granted permission for the app to get their details?

Database-wide equivalent of SET IDENTITY_INSERT OFF

sql-server identity identity-insert

In my eternal saga to insert 1.4 million rows of data from a SQL script, I've written a basic WinForms app that takes each line of the script and executes it individually.