динамическое размещение / освобождение 2D и 3D массивов

Я знаю об алгоритмах динамического выделения / освобождения 2D-массива, однако я не слишком уверен в том же для 3D-массивов.
Используя эти знания и немного симметрии, я придумал следующий код.
(Мне было трудно визуализировать в 3D во время кодирования).

Пожалуйста, прокомментируйте правильность и предложите любую лучшую альтернативу (с точки зрения эффективности или интуитивно), если таковая имеется.
Кроме того, я думаю, что к этим 2D и 3D массивам можно обращаться как к статическим массивам, таким как arr2D [2] [3] и
arr3D [2] [3] [2]. Правильно?

Код для 2D

//allocate a 2D array
int** allocate2D(int rows,int cols)
{
    int **arr2D;
    int i;

    arr2D = (int**)malloc(rows*sizeof(int*));
    for(i=0;i<rows;i++)
    {
        arr2D[i] = (int*)malloc(cols*sizeof(int));
    }
}

//deallocate a 2D array
void deallocate2D(int** arr2D,int rows)
{
    int i;

    for(i=0;i<rows;i++)
    {
        free(arr2D[i]);
    }

    free(arr2D);
}  

Код для 3D

//allocate a 3D array
int*** allocate3D(int l,int m,int n)
{
int ***arr3D;
int i,j,k;

arr3D = (int***)malloc(l * sizeof(int **));

for(i=0;i<l;i++)
{
    arr3D[i] = (int**)malloc(m * sizeof(int*));
    for(j=0;j<m;j++)
    {
        arr3D[i][j] = (int*)malloc(n*sizeof(int));
    }
}

return arr3D;
}

//deallocate a 3D array
void deallocate3D(int arr3D,int l,int m)
{
    int i,j;

    for(i=0;i<l;i++)
    {
        for(int j=0;j<m;j++)
        {
            free(arr3D[i][j]);
        }
        free(arr3D[i]);
    }
    free(arr3D);
}

Ответы на вопрос(4)

Ваш ответ на вопрос