Alex Rivera | Logout

Malloc a 3-Dimensional array in C?

Asked 2010-02-21T14:32:56.937
36

I'm translating some MATLAB code into C and the script I'm converting makes heavy use of 3D arrays with 10*100*300 complex entries. The size of the array also depends on the sensor's input, ideally the array should be allocated dynamically. So far I've tried two approaches the first being a flat 1D array along the lines of

value = array[x + (y*xSize) + (z*ySize*xSize)]

Which hurts my brain to use. I've also tried an array of an array of pointers

int main () {
  int ***array = malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    *array[i] = malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}

Which gives a seg fault when I try to assign data.

In a perfect world, I'd like to use the second method with the array notation for cleaner, easier programming. Is there a better way to dynamically allocate a three-dimensional array in C?

Edit
Report

2 Answers

16

As others have said, it is probably better to allocate one contiguous chunk of memory, and then figure out the indexing yourself. You can write a function to do so if you want. But since you seem to be interested in knowing how to deal with the multiple malloc() case, here is an example:

First, I define a function free_data(), which frees an int *** with xlen and ylen as the first two dimension sizes. We don't need a zlen parameter just like free() doesn't take the length of the pointer being freed.

void free_data(int ***data, size_t xlen, size_t ylen)
{
    size_t i, j;

    for (i=0; i < xlen; ++i) {
        if (data[i] != NULL) {
            for (j=0; j < ylen; ++j)
                free(data[i][j]);
            free(data[i]);
        }
    }
    free(data);
}

The function loops over the pointer data, finds out the ith int ** pointer data[i]. Then, for a given int ** pointer, it loops over it, finding out the jth int * in data[i][j], and frees it. It also needs to free data[i] once it has freed all data[i][j], and finally, it needs to free data itself.

Now to the allocation function. The function is a bit complicated by error checking. In particular, since there are 1 + xlen + xlen*ylen malloc calls, we have to be able to handle a failure in any of those calls, and free all the memory we allocated so far. To make things easier, we rely on the fact that free(NULL) is no-op, so we set all the pointers at a given level equal to NULL before we try to allocate them, so that if an error happens, we can free all of the pointers.

Other than that, the function is simple enough. We first allocate space for xlen

answered 2010-02-21T18:00:27.383
0

add #include "stdlib.h" and remove the * from *array[i] and it will run when compiled in gcc 4.4.1 on Ubuntu

also if you add print statements you can find your bugs quicker

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

int main () {
  int ***array = malloc(3*sizeof(int**));
  int i, j;

  printf("%s\n","OK");

  for (i = 0; i < 3; i++) {
    printf("i = %i \n",i);
    array[i] = malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      printf("i,j = %i,%i \n",i,j);
      array[i][j] = malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}
answered 2010-02-21T14:47:04.097

Your Answer