bob.sacamento bob.sacamento - 1 year ago 69
C Question

Allocating contiguous memory for a 3D array in C

I need to allocate contiguous space for a 3D array. (EDIT:) I GUESS I SHOULD HAVE MADE THIS CLEAR IN THE FIRST PLACE but in the actual production code, I will not know the dimensions of the array until run time. I provided them as constants in my toy code below just to keep things simple. I know the potential problems of insisting on contiguous space, but I just have to have it. I have seen how to do this for a 2D array, but apparently I don't understand how to extend the pattern to 3D. When I call the function to free up the memory,

, I get an error:

lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated

Would appreciate it if anyone could tell me what the fix is. Code is here:

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

int ***calloc_3d_arr(int sizes[3]){

int ***a;
int i,j;

a = calloc(sizes[0],sizeof(int**));
a[0] = calloc(sizes[0]*sizes[1],sizeof(int*));
a[0][0] = calloc(sizes[0]*sizes[1]*sizes[2],sizeof(int));

for (j=0; j<sizes[0]; j++) {
a[j] = (int**)(a[0][0]+sizes[1]*sizes[2]*j);
for (i=0; i<sizes[1]; i++) {
a[j][i] = (int*)(a[j]) + sizes[2]*i;

return a;


void free_3d_arr(int ***arr) {

printf("lowest lvl\n");
printf("mid lvl\n");
free(arr[0]); // <--- This is a problem line, apparently.
printf("highest lvl\n");


int main() {

int ***a;
int sz[] = {5,4,3};
int i,j,k;

a = calloc_3d_arr(sz);

// do stuff with a



Answer Source

Since you are using C, I would suggest that you use real multidimensional arrays:

int (*a)[sz[1]][sz[2]] = calloc(sz[0]*sizeof(*a));

This allocates contiguous storage for your 3D array. Note that the sizes can be dynamic since C99. You access this array exactly as you would with your pointer arrays:

for(int i = 0; i < sz[0]; i++) {
    for(int j = 0; j < sz[1]; j++) {
        for(int k = 0; k < sz[2]; k++) {
            a[i][j][k] = 42;

However, there are no pointer arrays under the hood, the indexing is done by the magic of pointer arithmetic and array-pointer-decay. And since a single calloc() was used to allocate the thing, a single free() suffices to get rid of it:

free(a);    //that's it.