Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory allocation in C language - 3D array

Tags:

c

memory

malloc

I want to allocate memory for a data cube in C language. I mean, I need to allocate a 3D array. My code, however, returns a segmentation fault and I don't know why.

I believe my loops are right, but the fact is, my code doesn't work.

This is my code:

int malloc3dfloat(float ****array, int q, int r, int s) {
    // allocate the q*r*s contiguous items 
    float *p = (float *) malloc(q*r*s*sizeof(float));
    if (!p) return -1;

    // allocate the row pointers into the memory 
    (*array) = (float ***) malloc(q*sizeof(float**));
    if (!(*array)) {
       free(p);
       return -1;
    }
    for (int i=0; i<q; i++)
    {
        (*array)[i] = (float **) malloc(r*sizeof(float*));
        if (!(*array[i])) 
        {
        free(p);
        return -1;
        }
    }

    //set up the pointers into the contiguous memory
    for (int i=0; i<q; i++)
    {
        for (int j=0; j<r; j++)
        { 
            (*array)[i][j] = &(p[(i*r+j)*s]);
        }
    }

    return 0;
}
like image 646
Nei Davi Figueiredo Avatar asked Dec 30 '22 12:12

Nei Davi Figueiredo


2 Answers

Just use Variable Length Array with dynamic storage.

float (*array)[r][s]=calloc(q, sizeof *array);

That's all!

Now use array[i][j][k] syntax to access individual elements.

like image 112
tstanisl Avatar answered Jan 07 '23 17:01

tstanisl


int vs. size_t math

int q, int r, int s
...

//                   v---v Product calculated using int math
// float *p = malloc(q*r*s*sizeof(float));

// Less chance of overflow
float *p = malloc(sizeof (float) * q*r*s);
// or even better 
float *p = malloc(sizeof *p * q*r*s);
//                        ^-------^ Product calculated using wider of size_t and int math

OP's malloc3dfloat() neither allocates a true 3D nor a jagged array, but a hybrid of the two.

To allocate a jagged one:

 // Full out-of-memory handling omitted for brevity
 int malloc3dfloat_j(float ****array, int q, int r, int s) {
   float ***a = malloc(sizeof *a * q);
   if (a == NULL) ...
   
   for (int qi = 0; qi < q; qi++) {  
     a[qi] = malloc(sizeof a[qi][0] * r);
     if (a[qi] == NULL) ...
  
     for (int ri = 0; ri < r; ri++) {  
       a[qi][ri] = malloc(sizeof a[qi][ri][0] * s);
       if (a[qi][ri] == NULL) ...
     }
   }

   *array = a;
   return 0;
 }
like image 29
chux - Reinstate Monica Avatar answered Jan 07 '23 16:01

chux - Reinstate Monica