define 5D object with memory allocation - c

I need to clear memory of 5D object, so first I need to define it with memory allocation.
My previous object definition was:
double I_object[N_GROUPS][NN][NN][NN][NN]={0};
I replaced it by code below and c file compiles but c program crashes :(
I_object=(double *****) malloc(sizeof(double *****)*N_GROUPS);
for(i = 0; i < N_GROUPS; i++){
I_object[i]=(double ****) malloc(sizeof(double****)*NN);
for(j = 0; j < NN; j++){
I_object[i][j]=(double ***) malloc(sizeof(double***)*NN);
for(k = 0; k < NN; k++){
I_object[i][j][k]=(double **) malloc(sizeof(double**)*NN);
for(l = 0; l < NN; l++){
I_object[i][j][k][l]=(double *) malloc(sizeof(double*)*NN);
}
}
}
}
Please let me know if this 5D object definition is wrong or where I can find how to define 5D object using malloc.

You forgot to declare the type of I_object. Also, you need to declare i, j, k and l. Also, I wouldn't cast the result of malloc in C. Furthermore, the indirection levels are wrong in your sizeof() calls, which causes a problem in the last one, where there might be a difference between the sizes of a double and a double*.
With those changes, it looks like this:
#define N_GROUPS 3
#define NN 3
int main() {
double *****I_object = malloc(sizeof(double ****)*N_GROUPS);
for (size_t i = 0; i < N_GROUPS; i++) {
I_object[i] = malloc(sizeof(double***)*NN);
for (size_t j = 0; j < NN; j++) {
I_object[i][j] = malloc(sizeof(double**)*NN);
for (size_t k = 0; k < NN; k++) {
I_object[i][j][k] = malloc(sizeof(double*)*NN);
for (size_t l = 0; l < NN; l++) {
I_object[i][j][k][l] = malloc(sizeof(double)*NN);
}
}
}
}
}
Also, for future questions, I would recommend posting a Minimal, Complete, and Verifiable example. This way, people are much more willing (and capable) to help. For instance, I had to make assumptions about N_GROUPS and NN. Even with low values such as 100 for NN, the memory consumption would already be so high that it will likely cause problems, but without a MCVE, it's hard to tell.

Instead of having array of some pointer to other arrays of some pointers to other arrays of ....
simply use a pointer to array[nn][nn][nn][nn] of doubles.
Something like:
#define NN 2
#define N_GROUPS 4
int main(int argc, char* argv[])
{
double (*I_object)[NN][NN][NN][NN]; // Define pointer
I_object = calloc(N_GROUPS, sizeof * I_object); // Allocate and zero-init memory
I_object[3][1][1][1][1] = 42; // Use as 5D matrix
printf("%f\n", I_object[3][1][1][1][1]);
free(I_object); // Free memory
return 0;
}

Related

C allocate 'array pointer' inside a function

Related to dynamic allocation inside a function, most questions & answers are based on double pointers.
But I was recommended to avoid using double pointer unless I have to, so I want to allocate a 'array pointer' (not 'array of pointer') and hide it inside a function.
int (*arr1d) = calloc(dim1, sizeof(*arr1d));
int (*arr2d)[dim2] = calloc(dim1, sizeof(*arr2d));
Since the above lines are the typical dynamic-allocation of pointer of array, I tried the following.
#include <stdio.h>
#include <stdlib.h>
int allocateArray1D(int n, int **arr) {
*arr = calloc(n, sizeof(*arr));
for (int i = 0; i < n; i++) {
(*arr)[i] = i;
}
return 0;
}
int allocateArray2D(int nx, int ny, int *(*arr)[ny]) {
*arr[ny] = calloc(nx, sizeof(*arr));
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
int main() {
int nx = 3;
int ny = 2;
int *arr1d = NULL; // (1)
allocateArray1D(nx, &arr1d);
int(*arr2d)[ny] = NULL; // (2)
allocateArray2D(nx, ny, &arr2d);
for (int i = 0; i < nx; i++) {
printf("arr1d[%d] = %d \n", i, arr1d[i]);
}
printf("\n");
printf("arr2d \n");
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
printf(" %d ", arr2d[i][j]);
}
printf("\n");
}
return 0;
}
And the error message already comes during the compilation.
03.c(32): warning #167: argument of type "int (**)[ny]" is incompatible with parameter of type "int *(*)[*]"
allocateArray2D(nx, ny, &arr2d);
^
It is evident from the error message that it has been messed up with the argument types (that I wrote as int *(*arr)[ny]) but what should I have to put there? I tried some variants like int *((*arr)[ny]), but didn't work).
And if I remove the 2D parts, then the code well compiles, and run as expected. But I wonder if this is the right practice, at least for 1D case since there are many examples where the code behaves as expected, but in fact there were wrong or un-standard lines.
Also, the above code is not satisfactory in the first place. I want to even remove the lines in main() that I marked as (1) and (2).
So in the end I want a code something like this, but all with the 'array pointers'.
int **arr2d;
allocateArray2D(nx, ny, arr2d);
How could this be done?
You need to pass the array pointer by reference (not pass an array pointer to an array of int*):
int *(*arr)[ny] -> int (**arr)[ny]
The function becomes:
int allocateArray2D(int nx, int ny, int (**arr)[ny]) {
*arr = calloc(nx, sizeof(int[ny])); // or sizeof(**arr)
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
For details, check out Correctly allocating multi-dimensional arrays
Best practices with malloc family is to always check if allocation succeeded and always free() at the end of the program.
As a micro-optimization, I'd rather recommend to use *arr = malloc( sizeof(int[nx][ny]) );, since calloc just creates pointless overhead bloat in the form of zero initialization. There's no use of it here since every item is assigned explicitly anyway.
Wrong parameter type
Strange allocation
Wrong size type
I would return the array as void * too (at least to check if allocation did not fail).
void *allocateArray2D(size_t nx, size_t ny, int (**arr)[ny]) {
//*arr = calloc(nx, sizeof(**arr)); calloc is not needed here as you assign values to the array
*arr = malloc(nx * sizeof(**arr));
for (size_t i = 0; i < nx; i++) {
for (size_t j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return *arr;
}

Creating a dynamic array of arrays using pointers

I'm trying to create a dynamic array of arrays. So, for example, let's look at Pascal's Triangle:
1
11
121
1331
14641
...
...
This is basically an array of length N, that has at each index an array of i+1.
How exactly do we set that up?
I've tried a little bit using pointers.
I set up an array of pointers like such:
int *arr[N];
Then I need a pointer i to point to an array of i+1, so I did:
int *i = 0;
for(int j = 0; j < N; j++){
int numArr[j+1];
arr[*i] = numArr;
*i++;
}
Am I going the right direction for this? Because I believe I'm supposed to allocate memory for this as I must use free() later. Would I use malloc() for each array initialization?
The code could be made extremely simple, if you know what you're doing:
int *arr = malloc(N * sizeof(int*));
int i;
for (i = 0; i < N; ++i) {
arr[i] = malloc(sizeof(int) * (i + 1));
}
Of course, you'll need corresponding calls to free() further down the line, like this:
for (i = 0; i < N; ++i) {
free(arr[i]);
}
free(arr);

Quadruple pointer and memcpy() in C

First of all, I know triple and quadruple pointers are bad practice and are ugly, that's not the point of this question, I'm trying to understand how they work. I'm aware using a struct would be much better.
I am trying to write a function that does some memory operations using memmove() and memcpy() on triple and double pointers that are passed-by-reference (or the C version of that). My memmove() works fine, but the memcpy() yields a SIGSEGV. Here's a minimal example
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define UNDO_DEPTH 25
void boardSave(int ***board, int game_sz, int ****history) {
// Shift history to the right
memmove(*history + 1, *history, (UNDO_DEPTH - 1) * sizeof(**history));
// Copy board into history
for (int row = 0; row < game_sz; ++row) {
memcpy((*history)[0][row], (*board)[row], game_sz * sizeof((**board)[row]));
}
}
int main(){
// Game
int game_sz = 5;
// Allocate array for the board
int **board = calloc(game_sz, sizeof(int *));
for (int i = 0; i < game_sz; ++i) board[i] = calloc(game_sz, sizeof(int));
// Allocate array for the history
int ***history = calloc(UNDO_DEPTH, sizeof(int **));
for (int i = 0; i < UNDO_DEPTH; ++i) {
history[i] = calloc(game_sz, sizeof(int *));
for (int j = 0; j < game_sz; ++j) {
history[i][j] = calloc(game_sz, sizeof(int));
}
}
board[0][0] = 1;
boardSave(&board, game_sz, &history);
}
The objective of boardSave() here is to copy board onto history[0]. What am I doing wrong? Why is this causing a segmentation fault?
In the main function you make history point to an array of UNDO_DEPTH pointers, each of which points to a board that has its own allocation. Since memmove moves a contiguous memory blocks, you cannot move the content of all those boards with memmove.
However, you could move down the pointers in that history array, leaving the board allocations untouched.
Just doing a single memmove would require you to free memory of the last board shuffled off, and allocate memory for the new board. But you could recycle that memory by moving the last pointer to the start instead.
Now, there is no need to pass the addresses of board and history to the boardSave function. It just makes your code more complicated for no reason. The simpler version would be:
void boardSave(int **board, int game_sz, int ***history)
{
// Save the last board
int ** last_board = history[UNDO_DEPTH - 1];
// Shuffle down all the boards
memmove( &history[1], &history[0], (UNDO_DEPTH - 1) * sizeof history[0] );
// Put the old last board on the front
history[0] = last_board;
// Copy board into front of history
copy_board( game_sz, history[0], board );
}
// Put a prototype for this earlier in the code. I think it makes
// the boardSave function clearer to use a separate function for this
// operation, which you might end up using on its own anyway.
//
void copy_board( int game_sz, int **dest, int **src )
{
for(int row = 0; row < game_sz; ++row)
memcpy(dest[row], src[row], game_sz * sizeof dest[0][0]);
}
Personally I'd prefer to avoid memcpy in the last function and just write a simple loop that is obviously correct. The compiler will optimize it to use memcpy anyway, but without the possibility of making an error in the memcpy parameters:
for(int row = 0; row < game_sz; ++row)
for (int col = 0; col < game_sz; ++col)
dest[row][col] = src[row][col];
Similar comments would apply to the use of memmove actually.
I would also make some use of const in the function signatures, so that a compiler error is generated if I accidentally switched the "dest" and "src" arguments. But I left that out at this stage for simplicitly.
In main the call would now be:
boardSave(board, game_sz, history);
If you reeeeealy want to pass pointers for practice then I would "de-point" them at the start of the function:
void complicated_boardSave(int ***p_board, int game_sz, int ****p_history)
{
int *** history = *p_history;
int ** board = *p_board;
// rest of code the same
I understand you want to challenge pointers.
I wanted provide a solution that utilizes single pointer.
As a matter of fact, you don't need to use a pointer at all.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int game_sz = 5;
#define UNDO_DEPTH 25
void boardSave(int *board[game_sz], int game_sz, int *history[UNDO_DEPTH]
[game_sz])
{
int i,j,k;
for( i = 0; i < UNDO_DEPTH - 1; i++)
for( j = 0; j < game_sz; j ++ )
for( k = 0; j < game_sz; j ++ )
history[i+1][j][k] = history[i][j][k];
for( i = 0; i < game_sz - 1; i++)
for( j = 0; j < game_sz; j++ )
history[0][i][j] = board[i][j];
}
int
main(void)
{
int *board[game_sz];
int *history[UNDO_DEPTH][game_sz];
int i, j;
for (i = 0; i < game_sz; ++i)
board[i] = calloc(game_sz, sizeof(int));
board[0][0] = 1;
// Allocate array for the history
for ( i = 0; i < UNDO_DEPTH; ++i)
for ( j = 0; j < game_sz; ++j)
history[i][j] = calloc(game_sz, sizeof(int));
boardSave( board, game_sz, history);
return 0;
}

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, free_3d_arr, 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");
free(arr[0][0]);
printf("mid lvl\n");
free(arr[0]); // <--- This is a problem line, apparently.
printf("highest lvl\n");
free(arr);
}
int main() {
int ***a;
int sz[] = {5,4,3};
int i,j,k;
a = calloc_3d_arr(sz);
// do stuff with a
free_3d_arr(a);
}
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.
You can do something like this:
int ***allocateLinearMemory(int x, int y, int z)
{
int *p = (int*) malloc(x * y * z * sizeof(int));
int ***q = (int***) malloc(x * sizeof(int**));
for (int i = 0; i < x; i++)
{
q[i] = (int**) malloc(y * sizeof(int*));
for (int j = 0; j < y; j++)
{
int idx = x*j + x*y*i;
q[i][j] = &p[idx];
}
}
return q;
}
void deallocateLinearMemory(int x, int ***q)
{
free(q[0][0]);
for(int i = 0; i < x; i++)
{
free(q[i]);
}
free(q);
}
I use it and works fine.

double free or corruption 3d array in C

I get a 'double free or corruption' error while freeing up an 3d array. Can anyone please tell me where is the problem in the code? The size of the array is 2*N*N. Value of N here is 100. Even without casting, same result.
Here is the code:
// Mallocing
double ***h = malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = malloc(N * sizeof(double*));
for(j = 0; j < N; j++) {
h[i][j] = malloc(N * sizeof(double));
}
}
// Freeing
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++) {
free(h[i][j]);
}
free(h[i]);
}
free(h);
The program works fine but at the end I get an error 'double free or corruption (!prev): 0x08cd24f8'
Aborted (core dumped).
For the first dimension, you allocate 2 elements:
double ***h = (double***) malloc(2 * (sizeof(double**)));
But you treat it as if it had N elements:
for(i = 0; i < N; i++) {
h[i] = ...
Change outermost loop comparison on allocation and free to:
for(i = 0; i < 2; i++) {
Also don't cast return value of malloc. Also, your code is missing error handling, and will break if allocation fails.
As fas as I can see you allocate 2 items, then fill N of them.
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = (double**) malloc(N * sizeof(double*));
....
....
}
You're overwriting not allocated space if N>2...
The problem's here:
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
// ...
}
You only malloc 2 elements, and iterate over N.
I guess you wanted to have array of size N*N*N, but you ended up with 2*N*N instead.
So this:
double ***h = (double***) malloc(2 * (sizeof(double**)));
Should be:
double ***h = (double***) malloc(N * (sizeof(double**)));
If the value of N = 100 as in your comment then you need to allocate memory to hold N pointer-to-pointer where you have just 2 .
double ***h = malloc(N * (sizeof(double*)));
Don't cast malloc()
As others have pointed out, the specific problem causing the bug is you treating the dimension with 2 elements as if it had N elements.
The core reason for this however, is obfuscation. There are some rules I would strongly recommend you to follow:
Always allocate multi-dimensional arrays as true arrays allocated in adjacent memory. Reference.
Never allocate multi-dimensional arrays as pointer-to-pointer based lookup-tables that are fragmented all over the heap. Not only are they slower and make the code harder to read, they aren't actually arrays. You can't use them together with memcpy() etc.
Unfortunately there are countless of bad C programming teachers and bad books that preach fragmented pointer-to-pointer lookup-tables. So many programmers have to unlearn this, it is frightening...
Never use more than two levels of indirection in your program. There should never be a reason to do so, all it does is to turn your program less readable (Reference MISRA-C:2012 rule 18.5). This is actually known as "three star programming" and it's not a flattering term.
Never cast the result of malloc, because it is pointless to do so.
What you should do:
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
...
free(array);
Example:
#include <stdio.h>
#include <stdlib.h>
#define X 2
#define Y 3
#define Z 4
int main (void)
{
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
double count = 0.0;
for(int x=0; x<X; x++)
{
for(int y=0; y<Y; y++)
{
for(int z=0; z<Z; z++)
{
array[x][y][z] = count++;
printf("%f ", array[x][y][z]);
}
printf("\n");
}
printf("\n");
}
free(array);
return 0;
}
To compile this, you need a compiler which is not older than 16 years.

Resources